summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore11
-rw-r--r--COPYING202
-rw-r--r--Makefile.am63
-rw-r--r--README.md46
-rwxr-xr-xbootstrap3
-rw-r--r--configure.ac44
-rw-r--r--examples/cube.scm557
-rw-r--r--examples/window.scm7
-rw-r--r--guix.scm149
-rw-r--r--pre-inst-env.in28
-rw-r--r--sdl3.scm67
-rw-r--r--sdl3/bindings/error.scm26
-rw-r--r--sdl3/bindings/events.scm750
-rw-r--r--sdl3/bindings/gpu.scm1190
-rw-r--r--sdl3/bindings/init.scm49
-rw-r--r--sdl3/bindings/pixels.scm41
-rw-r--r--sdl3/bindings/surface.scm36
-rw-r--r--sdl3/bindings/utils.scm133
-rw-r--r--sdl3/bindings/video.scm103
-rw-r--r--sdl3/config.scm.in26
-rw-r--r--sdl3/errors.scm54
-rw-r--r--sdl3/events.scm43
-rw-r--r--sdl3/gpu.scm966
-rw-r--r--sdl3/guardian.scm30
-rw-r--r--sdl3/video.scm85
25 files changed, 4709 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..af9fe7e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+*.go
+/Makefile.in
+/aclocal.m4
+/autom4te.cache/
+/build-aux/
+/config.log
+/configure
+/pre-inst-env
+/config.status
+/Makefile
+/sdl3/config.scm
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..bea7843
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,63 @@
+# guile-sdl3 -- Scheme bindings for SDL3
+# Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+GOBJECTS = $(SOURCES:%.scm=%.go)
+
+nobase_mod_DATA = $(SOURCES) $(NOCOMP_SOURCES)
+nobase_go_DATA = $(GOBJECTS)
+
+# Make sure source files are installed first, so that the mtime of
+# installed compiled files is greater than that of installed source
+# files. See
+# <http://lists.gnu.org/archive/html/guile-devel/2010-07/msg00125.html>
+# for details.
+guile_install_go_files = install-nobase_goDATA
+$(guile_install_go_files): install-nobase_modDATA
+
+CLEANFILES = $(GOBJECTS)
+EXTRA_DIST = $(SOURCES) $(NOCOMP_SOURCES)
+GUILE_WARNINGS = -Wunbound-variable -Warity-mismatch -Wformat
+SUFFIXES = .scm .go
+.scm.go:
+ $(AM_V_GEN)$(top_builddir)/pre-inst-env $(GUILE_TOOLS) compile $(GUILE_WARNINGS) -o "$@" "$<"
+
+moddir=$(prefix)/share/guile/site/$(GUILE_EFFECTIVE_VERSION)
+godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
+
+SOURCES = \
+ sdl3/config.scm \
+ sdl3/guardian.scm \
+ sdl3/bindings/utils.scm \
+ sdl3/bindings/error.scm \
+ sdl3/bindings/init.scm \
+ sdl3/bindings/video.scm \
+ sdl3/bindings/events.scm \
+ sdl3/bindings/pixels.scm \
+ sdl3/bindings/surface.scm \
+ sdl3/bindings/gpu.scm \
+ sdl3/errors.scm \
+ sdl3/video.scm \
+ sdl3/events.scm \
+ sdl3/gpu.scm \
+ sdl3.scm
+
+EXTRA_DIST += \
+ pre-inst-env.in \
+ README \
+ guix.scm \
+ run-example \
+ examples/hello.scm \
+ examples/hello.bmp \
+ examples/controller.scm
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e1dddef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+# Guile-SDL3
+
+Guile-SDL3 provides Guile Scheme bindings for the SDL3 library.
+
+## Requirements
+
+- Guile >= 3.0
+- SDL3 >= 3.0.0
+- make
+- pkg-config
+
+When building from a Git checkout, the following additional packages
+are required:
+
+- autoconf
+- automake
+- texinfo
+
+If you use Guix, a build environment can be created by running `guix
+shell`.
+
+## Building
+
+### From release tarball
+
+```
+./configure
+make
+make install
+```
+
+### From Git checkout
+
+```
+./bootstrap
+./configure
+make
+make install
+```
+
+## Contributing
+
+In lieu of a proper issue tracker, send patches and bug reports to
+<dthompson2@worcester.edu>. Discussion can be had on the #guile
+channel on the Libera.Chat IRC network or on the guile-user mailing
+lis.
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..872167c
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf -vif
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..83b8a81
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,44 @@
+# -*- Autoconf -*-
+#
+# guile-sdl3 -- Scheme bindings for SDL3
+# Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+AC_INIT(guile-sdl3, 0.1.0)
+AC_CONFIG_SRCDIR(sdl3)
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([color-tests -Wall -Wno-portability foreign])
+AM_SILENT_RULES([yes])
+
+AC_PATH_PROG([GUILE], [guile])
+AC_CONFIG_FILES([Makefile sdl3/config.scm])
+AC_CONFIG_FILES([pre-inst-env], [chmod +x pre-inst-env])
+
+GUILE_PKG([3.0])
+GUILE_PROGS
+
+GUILE_MODULE_REQUIRED([bstruct])
+
+# Core SDL3
+PKG_CHECK_MODULES([SDL3], [sdl3])
+PKG_CHECK_VAR([SDL3_LIBDIR], [sdl3], [libdir])
+AC_MSG_CHECKING([SDL3 library path])
+AS_IF([test "x$SDL3_LIBDIR" = "x"], [
+ AC_MSG_FAILURE([unable to find SDL3 library directory])
+], [
+ AC_MSG_RESULT([$SDL3_LIBDIR])
+])
+AC_SUBST([SDL3_LIBDIR])
+
+AC_OUTPUT
diff --git a/examples/cube.scm b/examples/cube.scm
new file mode 100644
index 0000000..74e131c
--- /dev/null
+++ b/examples/cube.scm
@@ -0,0 +1,557 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Adapted from https://github.com/thatcosmonaut/SDL/blob/main/test/testgpu_spinning_cube.c
+;;
+;;; Code:
+
+(use-modules (bstruct)
+ (ice-9 match)
+ (rnrs bytevectors)
+ (sdl3)
+ (sdl3 events)
+ (sdl3 gpu)
+ (sdl3 video))
+
+;; These SPIR-V blobs are taken directly from SDL.
+(define vert-spirv
+ #vu8(#x03 #x02 #x23 #x07 #x00 #x00 #x01 #x00 #x0b #x00 #x08 #x00
+ #x2a #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x11 #x00 #x02 #x00
+ #x01 #x00 #x00 #x00 #x0b #x00 #x06 #x00 #x01 #x00 #x00 #x00
+ #x47 #x4c #x53 #x4c #x2e #x73 #x74 #x64 #x2e #x34 #x35 #x30
+ #x00 #x00 #x00 #x00 #x0e #x00 #x03 #x00 #x00 #x00 #x00 #x00
+ #x01 #x00 #x00 #x00 #x0f #x00 #x09 #x00 #x00 #x00 #x00 #x00
+ #x04 #x00 #x00 #x00 #x6d #x61 #x69 #x6e #x00 #x00 #x00 #x00
+ #x09 #x00 #x00 #x00 #x0c #x00 #x00 #x00 #x18 #x00 #x00 #x00
+ #x22 #x00 #x00 #x00 #x03 #x00 #x03 #x00 #x02 #x00 #x00 #x00
+ #xc2 #x01 #x00 #x00 #x05 #x00 #x04 #x00 #x04 #x00 #x00 #x00
+ #x6d #x61 #x69 #x6e #x00 #x00 #x00 #x00 #x05 #x00 #x05 #x00
+ #x09 #x00 #x00 #x00 #x6f #x75 #x74 #x5f #x63 #x6f #x6c #x6f
+ #x72 #x00 #x00 #x00 #x05 #x00 #x05 #x00 #x0c #x00 #x00 #x00
+ #x69 #x6e #x5f #x63 #x6f #x6c #x6f #x72 #x00 #x00 #x00 #x00
+ #x05 #x00 #x06 #x00 #x16 #x00 #x00 #x00 #x67 #x6c #x5f #x50
+ #x65 #x72 #x56 #x65 #x72 #x74 #x65 #x78 #x00 #x00 #x00 #x00
+ #x06 #x00 #x06 #x00 #x16 #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x67 #x6c #x5f #x50 #x6f #x73 #x69 #x74 #x69 #x6f #x6e #x00
+ #x06 #x00 #x07 #x00 #x16 #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x67 #x6c #x5f #x50 #x6f #x69 #x6e #x74 #x53 #x69 #x7a #x65
+ #x00 #x00 #x00 #x00 #x06 #x00 #x07 #x00 #x16 #x00 #x00 #x00
+ #x02 #x00 #x00 #x00 #x67 #x6c #x5f #x43 #x6c #x69 #x70 #x44
+ #x69 #x73 #x74 #x61 #x6e #x63 #x65 #x00 #x06 #x00 #x07 #x00
+ #x16 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x67 #x6c #x5f #x43
+ #x75 #x6c #x6c #x44 #x69 #x73 #x74 #x61 #x6e #x63 #x65 #x00
+ #x05 #x00 #x03 #x00 #x18 #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x05 #x00 #x03 #x00 #x1c #x00 #x00 #x00 #x55 #x42 #x4f #x00
+ #x06 #x00 #x07 #x00 #x1c #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x6d #x6f #x64 #x65 #x6c #x56 #x69 #x65 #x77 #x50 #x72 #x6f
+ #x6a #x00 #x00 #x00 #x05 #x00 #x03 #x00 #x1e #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x05 #x00 #x05 #x00 #x22 #x00 #x00 #x00
+ #x69 #x6e #x5f #x70 #x6f #x73 #x69 #x74 #x69 #x6f #x6e #x00
+ #x47 #x00 #x04 #x00 #x09 #x00 #x00 #x00 #x1e #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x47 #x00 #x04 #x00 #x0c #x00 #x00 #x00
+ #x1e #x00 #x00 #x00 #x01 #x00 #x00 #x00 #x48 #x00 #x05 #x00
+ #x16 #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x0b #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x48 #x00 #x05 #x00 #x16 #x00 #x00 #x00
+ #x01 #x00 #x00 #x00 #x0b #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x48 #x00 #x05 #x00 #x16 #x00 #x00 #x00 #x02 #x00 #x00 #x00
+ #x0b #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x48 #x00 #x05 #x00
+ #x16 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x0b #x00 #x00 #x00
+ #x04 #x00 #x00 #x00 #x47 #x00 #x03 #x00 #x16 #x00 #x00 #x00
+ #x02 #x00 #x00 #x00 #x48 #x00 #x04 #x00 #x1c #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x05 #x00 #x00 #x00 #x48 #x00 #x05 #x00
+ #x1c #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x23 #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x48 #x00 #x05 #x00 #x1c #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x07 #x00 #x00 #x00 #x10 #x00 #x00 #x00
+ #x47 #x00 #x03 #x00 #x1c #x00 #x00 #x00 #x02 #x00 #x00 #x00
+ #x47 #x00 #x04 #x00 #x1e #x00 #x00 #x00 #x22 #x00 #x00 #x00
+ #x01 #x00 #x00 #x00 #x47 #x00 #x04 #x00 #x1e #x00 #x00 #x00
+ #x21 #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x47 #x00 #x04 #x00
+ #x22 #x00 #x00 #x00 #x1e #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x13 #x00 #x02 #x00 #x02 #x00 #x00 #x00 #x21 #x00 #x03 #x00
+ #x03 #x00 #x00 #x00 #x02 #x00 #x00 #x00 #x16 #x00 #x03 #x00
+ #x06 #x00 #x00 #x00 #x20 #x00 #x00 #x00 #x17 #x00 #x04 #x00
+ #x07 #x00 #x00 #x00 #x06 #x00 #x00 #x00 #x04 #x00 #x00 #x00
+ #x20 #x00 #x04 #x00 #x08 #x00 #x00 #x00 #x03 #x00 #x00 #x00
+ #x07 #x00 #x00 #x00 #x3b #x00 #x04 #x00 #x08 #x00 #x00 #x00
+ #x09 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x17 #x00 #x04 #x00
+ #x0a #x00 #x00 #x00 #x06 #x00 #x00 #x00 #x03 #x00 #x00 #x00
+ #x20 #x00 #x04 #x00 #x0b #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x0a #x00 #x00 #x00 #x3b #x00 #x04 #x00 #x0b #x00 #x00 #x00
+ #x0c #x00 #x00 #x00 #x01 #x00 #x00 #x00 #x2b #x00 #x04 #x00
+ #x06 #x00 #x00 #x00 #x0e #x00 #x00 #x00 #x00 #x00 #x80 #x3f
+ #x15 #x00 #x04 #x00 #x13 #x00 #x00 #x00 #x20 #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x2b #x00 #x04 #x00 #x13 #x00 #x00 #x00
+ #x14 #x00 #x00 #x00 #x01 #x00 #x00 #x00 #x1c #x00 #x04 #x00
+ #x15 #x00 #x00 #x00 #x06 #x00 #x00 #x00 #x14 #x00 #x00 #x00
+ #x1e #x00 #x06 #x00 #x16 #x00 #x00 #x00 #x07 #x00 #x00 #x00
+ #x06 #x00 #x00 #x00 #x15 #x00 #x00 #x00 #x15 #x00 #x00 #x00
+ #x20 #x00 #x04 #x00 #x17 #x00 #x00 #x00 #x03 #x00 #x00 #x00
+ #x16 #x00 #x00 #x00 #x3b #x00 #x04 #x00 #x17 #x00 #x00 #x00
+ #x18 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x15 #x00 #x04 #x00
+ #x19 #x00 #x00 #x00 #x20 #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x2b #x00 #x04 #x00 #x19 #x00 #x00 #x00 #x1a #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x18 #x00 #x04 #x00 #x1b #x00 #x00 #x00
+ #x07 #x00 #x00 #x00 #x04 #x00 #x00 #x00 #x1e #x00 #x03 #x00
+ #x1c #x00 #x00 #x00 #x1b #x00 #x00 #x00 #x20 #x00 #x04 #x00
+ #x1d #x00 #x00 #x00 #x02 #x00 #x00 #x00 #x1c #x00 #x00 #x00
+ #x3b #x00 #x04 #x00 #x1d #x00 #x00 #x00 #x1e #x00 #x00 #x00
+ #x02 #x00 #x00 #x00 #x20 #x00 #x04 #x00 #x1f #x00 #x00 #x00
+ #x02 #x00 #x00 #x00 #x1b #x00 #x00 #x00 #x3b #x00 #x04 #x00
+ #x0b #x00 #x00 #x00 #x22 #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x36 #x00 #x05 #x00 #x02 #x00 #x00 #x00 #x04 #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #xf8 #x00 #x02 #x00
+ #x05 #x00 #x00 #x00 #x3d #x00 #x04 #x00 #x0a #x00 #x00 #x00
+ #x0d #x00 #x00 #x00 #x0c #x00 #x00 #x00 #x51 #x00 #x05 #x00
+ #x06 #x00 #x00 #x00 #x0f #x00 #x00 #x00 #x0d #x00 #x00 #x00
+ #x00 #x00 #x00 #x00 #x51 #x00 #x05 #x00 #x06 #x00 #x00 #x00
+ #x10 #x00 #x00 #x00 #x0d #x00 #x00 #x00 #x01 #x00 #x00 #x00
+ #x51 #x00 #x05 #x00 #x06 #x00 #x00 #x00 #x11 #x00 #x00 #x00
+ #x0d #x00 #x00 #x00 #x02 #x00 #x00 #x00 #x50 #x00 #x07 #x00
+ #x07 #x00 #x00 #x00 #x12 #x00 #x00 #x00 #x0f #x00 #x00 #x00
+ #x10 #x00 #x00 #x00 #x11 #x00 #x00 #x00 #x0e #x00 #x00 #x00
+ #x3e #x00 #x03 #x00 #x09 #x00 #x00 #x00 #x12 #x00 #x00 #x00
+ #x41 #x00 #x05 #x00 #x1f #x00 #x00 #x00 #x20 #x00 #x00 #x00
+ #x1e #x00 #x00 #x00 #x1a #x00 #x00 #x00 #x3d #x00 #x04 #x00
+ #x1b #x00 #x00 #x00 #x21 #x00 #x00 #x00 #x20 #x00 #x00 #x00
+ #x3d #x00 #x04 #x00 #x0a #x00 #x00 #x00 #x23 #x00 #x00 #x00
+ #x22 #x00 #x00 #x00 #x51 #x00 #x05 #x00 #x06 #x00 #x00 #x00
+ #x24 #x00 #x00 #x00 #x23 #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x51 #x00 #x05 #x00 #x06 #x00 #x00 #x00 #x25 #x00 #x00 #x00
+ #x23 #x00 #x00 #x00 #x01 #x00 #x00 #x00 #x51 #x00 #x05 #x00
+ #x06 #x00 #x00 #x00 #x26 #x00 #x00 #x00 #x23 #x00 #x00 #x00
+ #x02 #x00 #x00 #x00 #x50 #x00 #x07 #x00 #x07 #x00 #x00 #x00
+ #x27 #x00 #x00 #x00 #x24 #x00 #x00 #x00 #x25 #x00 #x00 #x00
+ #x26 #x00 #x00 #x00 #x0e #x00 #x00 #x00 #x91 #x00 #x05 #x00
+ #x07 #x00 #x00 #x00 #x28 #x00 #x00 #x00 #x21 #x00 #x00 #x00
+ #x27 #x00 #x00 #x00 #x41 #x00 #x05 #x00 #x08 #x00 #x00 #x00
+ #x29 #x00 #x00 #x00 #x18 #x00 #x00 #x00 #x1a #x00 #x00 #x00
+ #x3e #x00 #x03 #x00 #x29 #x00 #x00 #x00 #x28 #x00 #x00 #x00
+ #xfd #x00 #x01 #x00 #x38 #x00 #x01 #x00))
+(define frag-spirv
+ #vu8( #x03 #x02 #x23 #x07 #x00 #x00 #x01 #x00 #x0b #x00 #x08 #x00
+ #x0d #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x11 #x00 #x02 #x00
+ #x01 #x00 #x00 #x00 #x0b #x00 #x06 #x00 #x01 #x00 #x00 #x00
+ #x47 #x4c #x53 #x4c #x2e #x73 #x74 #x64 #x2e #x34 #x35 #x30
+ #x00 #x00 #x00 #x00 #x0e #x00 #x03 #x00 #x00 #x00 #x00 #x00
+ #x01 #x00 #x00 #x00 #x0f #x00 #x07 #x00 #x04 #x00 #x00 #x00
+ #x04 #x00 #x00 #x00 #x6d #x61 #x69 #x6e #x00 #x00 #x00 #x00
+ #x09 #x00 #x00 #x00 #x0b #x00 #x00 #x00 #x10 #x00 #x03 #x00
+ #x04 #x00 #x00 #x00 #x07 #x00 #x00 #x00 #x03 #x00 #x03 #x00
+ #x02 #x00 #x00 #x00 #xc2 #x01 #x00 #x00 #x05 #x00 #x04 #x00
+ #x04 #x00 #x00 #x00 #x6d #x61 #x69 #x6e #x00 #x00 #x00 #x00
+ #x05 #x00 #x05 #x00 #x09 #x00 #x00 #x00 #x6f #x75 #x74 #x5f
+ #x63 #x6f #x6c #x6f #x72 #x00 #x00 #x00 #x05 #x00 #x05 #x00
+ #x0b #x00 #x00 #x00 #x69 #x6e #x5f #x63 #x6f #x6c #x6f #x72
+ #x00 #x00 #x00 #x00 #x47 #x00 #x04 #x00 #x09 #x00 #x00 #x00
+ #x1e #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x47 #x00 #x04 #x00
+ #x0b #x00 #x00 #x00 #x1e #x00 #x00 #x00 #x00 #x00 #x00 #x00
+ #x13 #x00 #x02 #x00 #x02 #x00 #x00 #x00 #x21 #x00 #x03 #x00
+ #x03 #x00 #x00 #x00 #x02 #x00 #x00 #x00 #x16 #x00 #x03 #x00
+ #x06 #x00 #x00 #x00 #x20 #x00 #x00 #x00 #x17 #x00 #x04 #x00
+ #x07 #x00 #x00 #x00 #x06 #x00 #x00 #x00 #x04 #x00 #x00 #x00
+ #x20 #x00 #x04 #x00 #x08 #x00 #x00 #x00 #x03 #x00 #x00 #x00
+ #x07 #x00 #x00 #x00 #x3b #x00 #x04 #x00 #x08 #x00 #x00 #x00
+ #x09 #x00 #x00 #x00 #x03 #x00 #x00 #x00 #x20 #x00 #x04 #x00
+ #x0a #x00 #x00 #x00 #x01 #x00 #x00 #x00 #x07 #x00 #x00 #x00
+ #x3b #x00 #x04 #x00 #x0a #x00 #x00 #x00 #x0b #x00 #x00 #x00
+ #x01 #x00 #x00 #x00 #x36 #x00 #x05 #x00 #x02 #x00 #x00 #x00
+ #x04 #x00 #x00 #x00 #x00 #x00 #x00 #x00 #x03 #x00 #x00 #x00
+ #xf8 #x00 #x02 #x00 #x05 #x00 #x00 #x00 #x3d #x00 #x04 #x00
+ #x07 #x00 #x00 #x00 #x0c #x00 #x00 #x00 #x0b #x00 #x00 #x00
+ #x3e #x00 #x03 #x00 #x09 #x00 #x00 #x00 #x0c #x00 #x00 #x00
+ #xfd #x00 #x01 #x00 #x38 #x00 #x01 #x00))
+
+(define data-vert
+ #f32(
+ ;; Front face.
+ ;; Bottom left
+ -0.5 0.5 -0.5 1.0 0.0 0.0 ; red
+ 0.5 -0.5 -0.5 0.0 0.0 1.0 ; blue
+ -0.5 -0.5 -0.5 0.0 1.0 0.0 ; green
+ ;; Top right
+ -0.5 0.5 -0.5 1.0 0.0 0.0 ; red
+ 0.5 0.5 -0.5 1.0 1.0 0.0 ; yellow
+ 0.5 -0.5 -0.5 0.0 0.0 1.0 ; blue
+ ;; Left face
+ ;; Bottom left
+ -0.5 0.5 0.5 1.0 1.0 1.0 ; white
+ -0.5 -0.5 -0.5 0.0 1.0 0.0 ; green
+ -0.5 -0.5 0.5 0.0 1.0 1.0 ; cyan
+ ;; Top right
+ -0.5 0.5 0.5 1.0 1.0 1.0 ; white
+ -0.5 0.5 -0.5 1.0 0.0 0.0 ; red
+ -0.5 -0.5 -0.5 0.0 1.0 0.0 ; green
+ ;; Top face
+ ;; Bottom left
+ -0.5 0.5 0.5 1.0 1.0 1.0 ; white
+ 0.5 0.5 -0.5 1.0 1.0 0.0 ; yellow
+ -0.5 0.5 -0.5 1.0 0.0 0.0 ; red
+ ;; Top right
+ -0.5 0.5 0.5 1.0 1.0 1.0 ; white
+ 0.5 0.5 0.5 0.0 0.0 0.0 ; black
+ 0.5 0.5 -0.5 1.0 1.0 0.0 ; yellow
+ ;; Right face
+ ;; Bottom left
+ 0.5 0.5 -0.5 1.0 1.0 0.0 ; yellow
+ 0.5 -0.5 0.5 1.0 0.0 1.0 ; magenta
+ 0.5 -0.5 -0.5 0.0 0.0 1.0 ; blue
+ ;; Top right
+ 0.5 0.5 -0.5 1.0 1.0 0.0 ; yellow
+ 0.5 0.5 0.5 0.0 0.0 0.0 ; black
+ 0.5 -0.5 0.5 1.0 0.0 1.0 ; magenta
+ ;; Back face
+ ;; Bottom left
+ 0.5 0.5 0.5 0.0 0.0 0.0 ; black
+ -0.5 -0.5 0.5 0.0 1.0 1.0 ; cyan
+ 0.5 -0.5 0.5 1.0 0.0 1.0 ; magenta
+ ;; Top right
+ 0.5 0.5 0.5 0.0 0.0 0.0 ; black
+ -0.5 0.5 0.5 1.0 1.0 1.0 ; white
+ -0.5 -0.5 0.5 0.0 1.0 1.0 ; cyan
+ ;; Bottom face
+ ;; Bottom left
+ -0.5 -0.5 -0.5 0.0 1.0 0.0 ; green
+ 0.5 -0.5 0.5 1.0 0.0 1.0 ; magenta
+ -0.5 -0.5 0.5 0.0 1.0 1.0 ; cyan
+ ;; Top right
+ -0.5 -0.5 -0.5 0.0 1.0 0.0 ; green
+ 0.5 -0.5 -0.5 0.0 0.0 1.0 ; blue
+ 0.5 -0.5 0.5 1.0 0.0 1.0 ; magenta
+ ))
+
+;; Initialize SDL. All we need is the video subsystem.
+(sdl-init '(video))
+
+;; Open window.
+(define window (make-window "SDL3 GPU" 800 600))
+
+;; Create GPU device.
+(define device (make-gpu-device '(spirv)))
+(claim-window-for-gpu-device! device window)
+
+;; Create shaders.
+(define shader-vert (make-gpu-shader device 'vertex 'spirv vert-spirv
+ #:uniform-buffers 1))
+(define shader-frag (make-gpu-shader device 'fragment 'spirv frag-spirv))
+
+;; Create empty vertex buffer
+(define nbytes-vert (bytevector-length data-vert))
+(define buffer-vert (make-gpu-buffer device nbytes-vert '(vertex)))
+(set-gpu-buffer-name! device buffer-vert "vertex buffer")
+
+;; Create transfer buffer and copy vertex data into it.
+(define buffer-transfer (make-gpu-transfer-buffer device nbytes-vert 'upload))
+(define mapped (map-gpu-transfer-buffer! device buffer-transfer nbytes-vert))
+(bytevector-copy! data-vert 0 mapped 0 nbytes-vert)
+(unmap-gpu-transfer-buffer! device buffer-transfer)
+
+;; Upload vertex data to vertex buffer.
+(define cmd (acquire-gpu-command-buffer device))
+(define copy-pass (begin-gpu-copy-pass cmd))
+(upload-to-gpu-buffer copy-pass buffer-transfer 0 buffer-vert 0 nbytes-vert)
+(end-gpu-copy-pass copy-pass)
+(submit-gpu-command-buffer! cmd)
+(release-gpu-transfer-buffer! device buffer-transfer)
+
+;; Figure out our sample rate.
+(define swapchain-texture-format (gpu-swapchain-texture-format device window))
+(define sample-count
+ (if (gpu-texture-supports-sample-count? device swapchain-texture-format 4)
+ 4 1))
+
+;; Setup graphics pipeline.
+(define color-target-desc
+ (make-gpu-color-target-description
+ #:format swapchain-texture-format))
+(define target-info
+ (make-gpu-graphics-pipeline-target-info
+ #:color-targets (vector color-target-desc)
+ #:depth-stencil-format 'd16-unorm))
+(define depth-stencil-state
+ (make-gpu-depth-stencil-state
+ #:compare-op 'less-or-equal))
+(define multisample-state
+ (make-gpu-multisample-state
+ #:sample-count sample-count))
+(define vertex-buffer-desc
+ (make-gpu-vertex-buffer-description
+ #:slot 0
+ #:pitch (* 4 6)))
+(define vertex-attrib-position
+ (make-gpu-vertex-attribute
+ #:buffer-slot 0
+ #:format 'float3
+ #:location 0))
+(define vertex-attrib-color
+ (make-gpu-vertex-attribute
+ #:buffer-slot 0
+ #:format 'float3
+ #:location 1
+ #:offset (* 4 3)))
+(define vertex-input-state
+ (make-gpu-vertex-input-state
+ #:vertex-buffer-descriptions (vector vertex-buffer-desc)
+ #:vertex-attributes (vector vertex-attrib-position
+ vertex-attrib-color)))
+(define pipeline
+ (make-gpu-graphics-pipeline device
+ #:vertex-shader shader-vert
+ #:fragment-shader shader-frag
+ #:vertex-input-state vertex-input-state
+ #:multisample-state multisample-state
+ #:depth-stencil-state depth-stencil-state
+ #:target-info target-info))
+
+;; Shaders can be released once the pipeline has been built.
+(release-gpu-shader! device shader-vert)
+(release-gpu-shader! device shader-frag)
+
+;; Create textures.
+(define-values (width height) (window-size-in-pixels window))
+(define tex-depth
+ (make-gpu-texture device
+ #:format 'd16-unorm
+ #:width width
+ #:height height
+ #:sample-count sample-count
+ #:usage '(depth-stencil-target)))
+(define tex-msaa
+ (make-gpu-texture device
+ #:format swapchain-texture-format
+ #:width width
+ #:height height
+ #:sample-count sample-count))
+(define tex-resolve
+ (make-gpu-texture device
+ #:format swapchain-texture-format
+ #:width width
+ #:height height
+ #:usage '(color-target sampler)))
+
+;; Transformation matrices.
+(define pi 3.1415926535897932)
+(define tau (* 2.0 pi))
+(define-bstruct <mat4> (array 16 f32))
+(define (make-mat4) (bstruct-alloc <mat4>))
+(define (make-identity-mat4)
+ (bstruct-alloc
+ <mat4>
+ (0 1.0) (1 0.0) (2 0.0) (3 0.0)
+ (4 0.0) (5 1.0) (6 0.0) (7 0.0)
+ (8 0.0) (9 0.0) (10 1.0) (11 0.0)
+ (12 0.0) (13 0.0) (14 0.0) (15 1.0)))
+(define (mat4-identity! m)
+ (bstruct-set!
+ <mat4> m
+ (0 1.0) (1 0.0) (2 0.0) (3 0.0)
+ (4 0.0) (5 1.0) (6 0.0) (7 0.0)
+ (8 0.0) (9 0.0) (10 1.0) (11 0.0)
+ (12 0.0) (13 0.0) (14 0.0) (15 1.0)))
+(define (mat4-perspective! m fovy aspect znear zfar)
+ (let ((f (/ 1.0 (tan (* fovy 0.5)))))
+ (bstruct-set!
+ <mat4> m
+ (0 (/ f aspect)) (1 0.0) (2 0.0) (3 0.0)
+ (4 0.0) (5 f) (6 0.0) (7 0.0)
+ (8 0.0) (9 0.0) (10 (/ (+ znear zfar) (- znear zfar))) (11 -1.0)
+ (12 0.0) (13 0.0) (14 (/ (* 2.0 znear zfar) (- znear zfar))) (15 0.0))))
+(define (mat4-rotate! m angle x y z)
+ (let* ((c (cos angle))
+ (s (sin angle))
+ (xx (* x x))
+ (yy (* y y))
+ (zz (* z z))
+ (xy (* x y))
+ (xz (* x z))
+ (yz (* y z)))
+ (bstruct-set!
+ <mat4> m
+ (0 (+ xx (* c (- 1.0 xx))))
+ (1 (+ (- xy (* c xy)) (* s z)))
+ (2 (- xz (* c xz) (* s y)))
+ (3 0.0)
+ (4 (- xy (* c xy) (* s z)))
+ (5 (+ yy (* c (- 1.0 yy))))
+ (6 (+ (- yz (* c yz)) (* s x)))
+ (7 0.0)
+ (8 (+ (- xz (* c xz)) (* s y)))
+ (9 (- yz (* c yz) (* s x)))
+ (10 (+ zz (* c (- 1.0 zz))))
+ (11 0.0)
+ (12 0.0)
+ (13 0.0)
+ (14 0.0)
+ (15 1.0))))
+(define (mat4-mult! a b c)
+ (let ((a0 (bstruct-ref <mat4> a 0))
+ (a1 (bstruct-ref <mat4> a 1))
+ (a2 (bstruct-ref <mat4> a 2))
+ (a3 (bstruct-ref <mat4> a 3))
+ (a4 (bstruct-ref <mat4> a 4))
+ (a5 (bstruct-ref <mat4> a 5))
+ (a6 (bstruct-ref <mat4> a 6))
+ (a7 (bstruct-ref <mat4> a 7))
+ (a8 (bstruct-ref <mat4> a 8))
+ (a9 (bstruct-ref <mat4> a 9))
+ (a10 (bstruct-ref <mat4> a 10))
+ (a11 (bstruct-ref <mat4> a 11))
+ (a12 (bstruct-ref <mat4> a 12))
+ (a13 (bstruct-ref <mat4> a 13))
+ (a14 (bstruct-ref <mat4> a 14))
+ (a15 (bstruct-ref <mat4> a 15))
+ (b0 (bstruct-ref <mat4> b 0))
+ (b1 (bstruct-ref <mat4> b 1))
+ (b2 (bstruct-ref <mat4> b 2))
+ (b3 (bstruct-ref <mat4> b 3))
+ (b4 (bstruct-ref <mat4> b 4))
+ (b5 (bstruct-ref <mat4> b 5))
+ (b6 (bstruct-ref <mat4> b 6))
+ (b7 (bstruct-ref <mat4> b 7))
+ (b8 (bstruct-ref <mat4> b 8))
+ (b9 (bstruct-ref <mat4> b 9))
+ (b10 (bstruct-ref <mat4> b 10))
+ (b11 (bstruct-ref <mat4> b 11))
+ (b12 (bstruct-ref <mat4> b 12))
+ (b13 (bstruct-ref <mat4> b 13))
+ (b14 (bstruct-ref <mat4> b 14))
+ (b15 (bstruct-ref <mat4> b 15)))
+ (bstruct-set!
+ <mat4> c
+ (0 (+ (* a0 b0) (* a1 b4) (* a2 b8) (* a3 b12)))
+ (1 (+ (* a0 b1) (* a1 b5) (* a2 b9) (* a3 b13)))
+ (2 (+ (* a0 b2) (* a1 b6) (* a2 b10) (* a3 b14)))
+ (3 (+ (* a0 b3) (* a1 b7) (* a2 b11) (* a3 b15)))
+ (4 (+ (* a4 b0) (* a5 b4) (* a6 b8) (* a7 b12)))
+ (5 (+ (* a4 b1) (* a5 b5) (* a6 b9) (* a7 b13)))
+ (6 (+ (* a4 b2) (* a5 b6) (* a6 b10) (* a7 b14)))
+ (7 (+ (* a4 b3) (* a5 b7) (* a6 b11) (* a7 b15)))
+ (8 (+ (* a8 b0) (* a9 b4) (* a10 b8) (* a11 b12)))
+ (9 (+ (* a8 b1) (* a9 b5) (* a10 b9) (* a11 b13)))
+ (10 (+ (* a8 b2) (* a9 b6) (* a10 b10) (* a11 b14)))
+ (11 (+ (* a8 b3) (* a9 b7) (* a10 b11) (* a11 b15)))
+ (12 (+ (* a12 b0) (* a13 b4) (* a14 b8) (* a15 b12)))
+ (13 (+ (* a12 b1) (* a13 b5) (* a14 b9) (* a15 b13)))
+ (14 (+ (* a12 b2) (* a13 b6) (* a14 b10) (* a15 b14)))
+ (15 (+ (* a12 b3) (* a13 b7) (* a14 b11) (* a15 b15))))))
+(define perspective (make-mat4))
+(define modelview (make-mat4))
+(define rotation (make-mat4))
+(define mvp (make-mat4))
+(define angle-x 0.0)
+(define angle-y 0.0)
+(define angle-z 0.0)
+(define aspect-ratio (exact->inexact (/ width height)))
+
+;; Setup various command buffer state.
+(define vertex-bindings
+ (vector (make-gpu-buffer-binding buffer-vert)))
+(define main-color-target
+ (if (= sample-count 1)
+ (make-gpu-color-target #f #:load-op 'clear)
+ (make-gpu-color-target tex-msaa
+ #:load-op 'clear
+ #:store-op 'resolve
+ #:resolve-texture tex-resolve
+ #:cycle? #t
+ #:cycle-resolve-texture? #t)))
+(define blit-info
+ (and (> sample-count 1)
+ (make-gpu-blit-info
+ #:source-texture tex-resolve
+ #:source-width width
+ #:source-height height
+ #:destination-texture tex-resolve
+ #:destination-width width
+ #:destination-height height)))
+(define color-targets (vector main-color-target))
+(define depth-target
+ (make-gpu-depth-stencil-target tex-depth
+ #:load-op 'clear
+ #:clear-depth 1.0
+ #:cycle? #t))
+
+(define (render)
+ (define cmd (acquire-gpu-command-buffer device))
+ ;; TODO: This could fail. Catch exception and try again next frame
+ ;; in that case.
+ (define-values (tex-swapchain width height)
+ (acquire-gpu-swapchain-texture cmd window))
+
+ ;; Setup transformation matrix.
+ (mat4-rotate! modelview angle-x 1.0 0.0 0.0)
+ (mat4-rotate! rotation angle-y 0.0 1.0 0.0)
+ (mat4-mult! modelview rotation modelview)
+ (mat4-rotate! rotation angle-z 0.0 1.0 0.0)
+ (mat4-mult! modelview rotation modelview)
+ (let ((z (bstruct-ref <mat4> modelview 14)))
+ (bstruct-set! <mat4> modelview (14 (- z 2.5))))
+ (mat4-perspective! perspective 45.0 aspect-ratio 0.01 100.0)
+ (mat4-mult! modelview perspective mvp)
+
+ ;; Setup matrix uniform buffer.
+ (call-with-values (lambda () (bstruct-unwrap <mat4> mvp))
+ (lambda (bv offset)
+ (push-gpu-vertex-uniform-data cmd 0 bv (bstruct-sizeof <mat4>) offset)))
+
+ ;; Step rotation.
+ (set! angle-x (+ angle-x 0.03))
+ (set! angle-y (+ angle-y 0.02))
+ (set! angle-z (+ angle-z 0.01))
+ (when (>= angle-x tau) (set! angle-x (- angle-x tau)))
+ (when (>= angle-y tau) (set! angle-y (- angle-y tau)))
+ (when (>= angle-z tau) (set! angle-z (- angle-z tau)))
+
+ ;; Write directly to swapchain texture when not multisampling.
+ (when (= sample-count 1)
+ (set-gpu-color-target-texture! main-color-target tex-swapchain))
+
+ ;; Draw the cube!
+ (define pass (begin-gpu-render-pass cmd color-targets depth-target))
+ (bind-gpu-graphics-pipeline pass pipeline)
+ (bind-gpu-vertex-buffers pass 0 vertex-bindings)
+ (draw-gpu-primitives pass 36 1)
+ (end-gpu-render-pass pass)
+
+ ;; Blit to swapchain texture when multisampling.
+ (when (> sample-count 1)
+ (set-gpu-blit-info-destination-texture! blit-info tex-swapchain)
+ (blit-gpu-texture cmd blit-info))
+
+ ;; Submit commands!
+ (submit-gpu-command-buffer! cmd))
+
+(define (handle-events)
+ (match (poll-event)
+ (#f #t)
+ (event
+ (match (event-type event)
+ ((or 'quit 'key-down) #f)
+ (_ (handle-events))))))
+
+(let lp ()
+ (when (handle-events)
+ (render)
+ (lp)))
+
+(release-gpu-texture! device tex-depth)
+(release-gpu-texture! device tex-msaa)
+(release-gpu-texture! device tex-resolve)
+(release-gpu-graphics-pipeline! device pipeline)
+(release-gpu-buffer! device buffer-vert)
+(release-window-from-gpu-device! device window)
+(destroy-gpu-device! device)
+(destroy-window! window)
diff --git a/examples/window.scm b/examples/window.scm
new file mode 100644
index 0000000..0a4d3f0
--- /dev/null
+++ b/examples/window.scm
@@ -0,0 +1,7 @@
+(use-modules (sdl3)
+ (sdl3 video))
+
+(sdl-init)
+(define window (make-window "Hello" 640 480))
+(sleep 3)
+(destroy-window! window)
diff --git a/guix.scm b/guix.scm
new file mode 100644
index 0000000..8e39021
--- /dev/null
+++ b/guix.scm
@@ -0,0 +1,149 @@
+;;; guile-sdl3 --- FFI bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; This file is part of guile-sdl3.
+;;;
+;;; Guile-sdl3 is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU Lesser General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; Guile-sdl3 is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU Lesser General Public
+;;; License along with guile-sdl3. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; GNU Guix development package. To build and install, run:
+;;
+;; guix package -f guix.scm
+;;
+;; To use as the basis for a development environment, run:
+;;
+;; guix shell
+;;
+;;; Code:
+
+(use-modules (gnu packages)
+ (gnu packages autotools)
+ (gnu packages fcitx)
+ (gnu packages freedesktop)
+ (gnu packages glib)
+ (gnu packages guile)
+ (gnu packages ibus)
+ (gnu packages linux)
+ (gnu packages pkg-config)
+ (gnu packages pulseaudio)
+ (gnu packages sdl)
+ (gnu packages texinfo)
+ (gnu packages vulkan)
+ (gnu packages xdisorg)
+ (gnu packages xorg)
+ (guix build-system cmake)
+ (guix build-system gnu)
+ (guix gexp)
+ (guix git)
+ (guix git-download)
+ ((guix licenses) #:prefix license:)
+ (guix packages))
+
+(define sdl3
+ (let ((commit "596fcfa6c4fd20e5a952c0a1b0147f2fa9f69198")
+ (revision "1"))
+ (package
+ (inherit sdl2)
+ (name "sdl3")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/libsdl-org/SDL")
+ (commit commit)))
+ (sha256
+ (base32
+ "0f3dx1r92crkf3l0iyf8rbmzba06dpcy90vha39i1jvdmifhyqbs"))))
+ (build-system cmake-build-system)
+ (arguments
+ (list
+ #:tests? #f
+ #:configure-flags
+ #~(list "-DSDL_KMSDRM=ON"
+ "-DSDL_ALSA_SHARED=OFF"
+ "-DSDL_PULSEAUDIO_SHARED=OFF"
+ "-DSDL_PIPEWIRE_SHARED=OFF"
+ "-DSDL_X11_SHARED=OFF"
+ "-DSDL_WAYLAND_SHARED=OFF"
+ "-DSDL_WAYLAND_LIBDECOR_SHARED=OFF"
+ "-DSDL_KMSDRM_SHARED=OFF"
+ (string-append "-DCMAKE_SHARED_LINKER_FLAGS=-Wl,-rpath,"
+ #$(this-package-input "eudev") "/lib"
+ ",-rpath,"
+ #$(this-package-input "vulkan-loader") "/lib"))))
+ (propagated-inputs
+ (list
+ alsa-lib
+ libxcursor ;enables X11 cursor support
+ libxkbcommon
+ libxrandr
+ pipewire
+ pulseaudio
+ wayland))
+ (inputs
+ (list
+ dbus
+ eudev ;for discovering input devices
+ fcitx
+ glib
+ ibus-minimal
+ libdecor
+ vulkan-loader
+ wayland-protocols)))))
+
+(define guile-bstruct
+ (let ((commit "3186036e116d3e885eae3970e0cad77289d922fd")
+ (revision "1"))
+ (package
+ (name "guile-bstruct")
+ (version "0.1.0-git")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://git.dthompson.us/guile-bstruct.git")
+ (commit commit)))
+ (sha256
+ (base32
+ "0128p1wdiad1sfifaa40w45899pii4mpw30aw3h1rc1dsgm6288m"))))
+ (build-system gnu-build-system)
+ (native-inputs (list automake autoconf pkg-config texinfo))
+ (inputs (list guile-3.0-latest))
+ (synopsis "Efficient binary structures for Guile")
+ (description "Guile-bstruct provides an efficient implementation of low-level binary
+structures for Guile Scheme.")
+ (home-page "https://dthompson.us/projects/guile-bstruct.html")
+ (license license:asl2.0))))
+
+(package
+ (name "guile-sdl3")
+ (version "0.1.0")
+ (source (git-checkout (url (dirname (current-filename)))))
+ (build-system gnu-build-system)
+ (arguments
+ '(#:make-flags '("GUILE_AUTO_COMPILE=0")
+ #:phases
+ (modify-phases %standard-phases
+ (add-after 'unpack 'bootstrap
+ (lambda _ (invoke "sh" "bootstrap"))))))
+ (native-inputs (list autoconf automake pkg-config texinfo))
+ (inputs (list guile-3.0-latest sdl3))
+ (propagated-inputs (list guile-bstruct))
+ (synopsis "Guile bindings for SDL3")
+ (description "Guile-SDL3 provides pure Guile Scheme bindings to the SDL3 C shared
+library via the foreign function interface.")
+ (home-page "https://git.dthompson.us/guile-sdl3.git")
+ (license license:asl2.0))
diff --git a/pre-inst-env.in b/pre-inst-env.in
new file mode 100644
index 0000000..067e358
--- /dev/null
+++ b/pre-inst-env.in
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# guile-sdl3 -- Scheme bindings for SDL3
+# Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+abs_top_srcdir="`cd "@abs_top_srcdir@" > /dev/null; pwd`"
+abs_top_builddir="`cd "@abs_top_builddir@" > /dev/null; pwd`"
+
+GUILE_LOAD_COMPILED_PATH="$abs_top_builddir${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH"
+GUILE_LOAD_PATH="$abs_top_builddir:$abs_top_srcdir${GUILE_LOAD_PATH:+:}:$GUILE_LOAD_PATH"
+export GUILE_LOAD_COMPILED_PATH GUILE_LOAD_PATH
+
+PATH="$abs_top_builddir/scripts:$PATH"
+export PATH
+
+exec "$@"
diff --git a/sdl3.scm b/sdl3.scm
new file mode 100644
index 0000000..1430116
--- /dev/null
+++ b/sdl3.scm
@@ -0,0 +1,67 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; SDL3 initialization and shutdown.
+;;
+;;; Code:
+
+(define-module (sdl3)
+ #:use-module (ice-9 match)
+ #:use-module (sdl3 bindings init)
+ #:use-module (sdl3 errors)
+ #:use-module (srfi srfi-1)
+ #:use-module (system foreign)
+ #:export (sdl-init
+ sdl-quit))
+
+(define (sdl-init subsystems)
+ "Initialize SDL @var{subsystems}, a list of symbols. By default, all
+subsystems are initialized.
+
+Valid subsystem names are:
+
+@itemize
+@item @code{audio}
+@item @code{video}
+@item @code{joystick}
+@item @code{haptic}
+@item @code{gamepad}
+@item @code{events}
+@item @code{sensor}
+@item @code{camera}
+@end itemize"
+ (sdl-assert 'sdl-init
+ (SDL_Init
+ (fold (lambda (name prev)
+ (logior (match name
+ ('audio SDL_INIT_AUDIO)
+ ('video SDL_INIT_VIDEO)
+ ('joystick SDL_INIT_JOYSTICK)
+ ('haptic SDL_INIT_HAPTIC)
+ ('gamepad SDL_INIT_GAMEPAD)
+ ('events SDL_INIT_EVENTS)
+ ('sensor SDL_INIT_SENSOR)
+ ('camera SDL_INIT_CAMERA)
+ (_ (raise (make-sdl-error 'sdl-init
+ #:message "invalid subsystem name"
+ #:irritants (list name)))))
+ prev))
+ 0 subsystems))))
+
+(define (sdl-quit)
+ "Clean up all initialized subsystems."
+ (SDL_Quit))
diff --git a/sdl3/bindings/error.scm b/sdl3/bindings/error.scm
new file mode 100644
index 0000000..71e5885
--- /dev/null
+++ b/sdl3/bindings/error.scm
@@ -0,0 +1,26 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_error.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings error)
+ #:use-module (sdl3 bindings utils)
+ #:export (SDL_GetError))
+
+(define-sdl SDL_GetError -> '*)
diff --git a/sdl3/bindings/events.scm b/sdl3/bindings/events.scm
new file mode 100644
index 0000000..f123b95
--- /dev/null
+++ b/sdl3/bindings/events.scm
@@ -0,0 +1,750 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level FFI binding utilities.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings events)
+ #:use-module (bstruct)
+ #:use-module (sdl3 bindings utils)
+ #:use-module (system foreign)
+ #:export (SDL_EventType
+ symbol->event-type
+ event-type->symbol
+ SDL_EVENT_FIRST
+ SDL_EVENT_QUIT
+ SDL_EVENT_TERMINATING
+ SDL_EVENT_LOW_MEMORY
+ SDL_EVENT_WILL_ENTER_BACKGROUND
+ SDL_EVENT_DID_ENTER_BACKGROUND
+ SDL_EVENT_WILL_ENTER_FOREGROUND
+ SDL_EVENT_DID_ENTER_FOREGROUND
+ SDL_EVENT_LOCALE_CHANGED
+ SDL_EVENT_SYSTEM_THEME_CHANGED
+ SDL_EVENT_DISPLAY_ORIENTATION
+ SDL_EVENT_DISPLAY_ADDED
+ SDL_EVENT_DISPLAY_REMOVED
+ SDL_EVENT_DISPLAY_MOVED
+ SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED
+ SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED
+ SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED
+ SDL_EVENT_WINDOW_SHOWN
+ SDL_EVENT_WINDOW_HIDDEN
+ SDL_EVENT_WINDOW_EXPOSED
+ SDL_EVENT_WINDOW_MOVED
+ SDL_EVENT_WINDOW_RESIZED
+ SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED
+ SDL_EVENT_WINDOW_METAL_VIEW_RESIZED
+ SDL_EVENT_WINDOW_MINIMIZED
+ SDL_EVENT_WINDOW_MAXIMIZED
+ SDL_EVENT_WINDOW_RESTORED
+ SDL_EVENT_WINDOW_MOUSE_ENTER
+ SDL_EVENT_WINDOW_MOUSE_LEAVE
+ SDL_EVENT_WINDOW_FOCUS_GAINED
+ SDL_EVENT_WINDOW_FOCUS_LOST
+ SDL_EVENT_WINDOW_CLOSE_REQUESTED
+ SDL_EVENT_WINDOW_HIT_TEST
+ SDL_EVENT_WINDOW_ICCPROF_CHANGED
+ SDL_EVENT_WINDOW_DISPLAY_CHANGED
+ SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED
+ SDL_EVENT_WINDOW_SAFE_AREA_CHANGED
+ SDL_EVENT_WINDOW_OCCLUDED
+ SDL_EVENT_WINDOW_ENTER_FULLSCREEN
+ SDL_EVENT_WINDOW_LEAVE_FULLSCREEN
+ SDL_EVENT_WINDOW_DESTROYED
+ SDL_EVENT_WINDOW_HDR_STATE_CHANGED
+ SDL_EVENT_KEY_DOWN
+ SDL_EVENT_KEY_UP
+ SDL_EVENT_TEXT_EDITING
+ SDL_EVENT_TEXT_INPUT
+ SDL_EVENT_KEYMAP_CHANGED
+ SDL_EVENT_KEYBOARD_ADDED
+ SDL_EVENT_KEYBOARD_REMOVED
+ SDL_EVENT_TEXT_EDITING_CANDIDATES
+ SDL_EVENT_MOUSE_MOTION
+ SDL_EVENT_MOUSE_BUTTON_DOWN
+ SDL_EVENT_MOUSE_BUTTON_UP
+ SDL_EVENT_MOUSE_WHEEL
+ SDL_EVENT_MOUSE_ADDED
+ SDL_EVENT_MOUSE_REMOVED
+ SDL_EVENT_JOYSTICK_AXIS_MOTION
+ SDL_EVENT_JOYSTICK_BALL_MOTION
+ SDL_EVENT_JOYSTICK_HAT_MOTION
+ SDL_EVENT_JOYSTICK_BUTTON_DOWN
+ SDL_EVENT_JOYSTICK_BUTTON_UP
+ SDL_EVENT_JOYSTICK_ADDED
+ SDL_EVENT_JOYSTICK_REMOVED
+ SDL_EVENT_JOYSTICK_BATTERY_UPDATED
+ SDL_EVENT_JOYSTICK_UPDATE_COMPLETE
+ SDL_EVENT_GAMEPAD_AXIS_MOTION
+ SDL_EVENT_GAMEPAD_BUTTON_DOWN
+ SDL_EVENT_GAMEPAD_BUTTON_UP
+ SDL_EVENT_GAMEPAD_ADDED
+ SDL_EVENT_GAMEPAD_REMOVED
+ SDL_EVENT_GAMEPAD_REMAPPED
+ SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN
+ SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION
+ SDL_EVENT_GAMEPAD_TOUCHPAD_UP
+ SDL_EVENT_GAMEPAD_SENSOR_UPDATE
+ SDL_EVENT_GAMEPAD_UPDATE_COMPLETE
+ SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED
+ SDL_EVENT_FINGER_DOWN
+ SDL_EVENT_FINGER_UP
+ SDL_EVENT_FINGER_MOTION
+ SDL_EVENT_CLIPBOARD_UPDATE
+ SDL_EVENT_DROP_FILE
+ SDL_EVENT_DROP_TEXT
+ SDL_EVENT_DROP_BEGIN
+ SDL_EVENT_DROP_COMPLETE
+ SDL_EVENT_DROP_POSITION
+ SDL_EVENT_AUDIO_DEVICE_ADDED
+ SDL_EVENT_AUDIO_DEVICE_REMOVED
+ SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED
+ SDL_EVENT_SENSOR_UPDATE
+ SDL_EVENT_PEN_PROXIMITY_IN
+ SDL_EVENT_PEN_PROXIMITY_OUT
+ SDL_EVENT_PEN_DOWN
+ SDL_EVENT_PEN_UP
+ SDL_EVENT_PEN_BUTTON_DOWN
+ SDL_EVENT_PEN_BUTTON_UP
+ SDL_EVENT_PEN_MOTION
+ SDL_EVENT_PEN_AXIS
+ SDL_EVENT_CAMERA_DEVICE_ADDED
+ SDL_EVENT_CAMERA_DEVICE_REMOVED
+ SDL_EVENT_CAMERA_DEVICE_APPROVED
+ SDL_EVENT_CAMERA_DEVICE_DENIED
+ SDL_EVENT_RENDER_TARGETS_RESET
+ SDL_EVENT_RENDER_DEVICE_RESET
+ SDL_EVENT_POLL_SENTINEL
+ SDL_EVENT_DISPLAY_FIRST
+ SDL_EVENT_DISPLAY_LAST
+ SDL_EVENT_WINDOW_FIRST
+ SDL_EVENT_WINDOW_LAST
+ SDL_EVENT_USER
+ SDL_EVENT_LAST
+ SDL_EVENT_ENUM_PADDING
+
+ SDL_CommonEvent
+ SDL_DisplayEvent
+ SDL_WindowEvent
+ SDL_KeyboardDeviceEvent
+ SDL_KeyboardEvent
+ SDL_TextEditingEvent
+ SDL_TextEditingCandidatesEvent
+ SDL_TextInputEvent
+ SDL_MouseDeviceEvent
+ SDL_MouseMotionEvent
+ SDL_MouseButtonEvent
+ SDL_MouseWheelEvent
+ SDL_JoyAxisEvent
+ SDL_JoyBallEvent
+ SDL_JoyHatEvent
+ SDL_JoyButtonEvent
+ SDL_JoyDeviceEvent
+ SDL_JoyBatteryEvent
+ SDL_GamepadAxisEvent
+ SDL_GamepadButtonEvent
+ SDL_GamepadDeviceEvent
+ SDL_GamepadTouchpadEvent
+ SDL_GamepadSensorEvent
+ SDL_AudioDeviceEvent
+ SDL_CameraDeviceEvent
+ SDL_TouchFingerEvent
+ SDL_PenProximityEvent
+ SDL_PenMotionEvent
+ SDL_PenTouchEvent
+ SDL_PenButtonEvent
+ SDL_PenAxisEvent
+ SDL_DropEvent
+ SDL_ClipboardEvent
+ SDL_SensorEvent
+ SDL_QuitEvent
+ SDL_UserEvent
+ SDL_Event
+
+ SDL_PumpEvents
+ SDL_HasEvent
+ SDL_HasEvents
+ SDL_FlushEvent
+ SDL_FlushEvents
+ SDL_PollEvent
+ SDL_WaitEvent
+ SDL_WaitEventTimeout
+ SDL_PushEvent))
+
+(define-enum SDL_EventType
+ symbol->event-type
+ event-type->symbol
+ (first SDL_EVENT_FIRST)
+ (quit SDL_EVENT_QUIT #x100)
+ (terminating SDL_EVENT_TERMINATING)
+ (low-memory SDL_EVENT_LOW_MEMORY)
+ (will-enter-background SDL_EVENT_WILL_ENTER_BACKGROUND)
+ (did-enter-background SDL_EVENT_DID_ENTER_BACKGROUND)
+ (will-enter-foreground SDL_EVENT_WILL_ENTER_FOREGROUND)
+ (did-enter-foreground SDL_EVENT_DID_ENTER_FOREGROUND)
+ (locale-changed SDL_EVENT_LOCALE_CHANGED)
+ (system-theme-changed SDL_EVENT_SYSTEM_THEME_CHANGED)
+ (display-orientation SDL_EVENT_DISPLAY_ORIENTATION #x151)
+ (display-added SDL_EVENT_DISPLAY_ADDED)
+ (display-removed SDL_EVENT_DISPLAY_REMOVED)
+ (display-moved SDL_EVENT_DISPLAY_MOVED)
+ (display-desktop-mode-changed SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED)
+ (display-current-mode-changed SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED)
+ (display-content-scale-changed SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED)
+ (window-shown SDL_EVENT_WINDOW_SHOWN #x202)
+ (window-hidden SDL_EVENT_WINDOW_HIDDEN)
+ (window-exposed SDL_EVENT_WINDOW_EXPOSED)
+ (window-moved SDL_EVENT_WINDOW_MOVED)
+ (window-resized SDL_EVENT_WINDOW_RESIZED)
+ (window-pixel-size-changed SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED)
+ (window-metal-view-resized SDL_EVENT_WINDOW_METAL_VIEW_RESIZED)
+ (window-minimized SDL_EVENT_WINDOW_MINIMIZED)
+ (window-maximized SDL_EVENT_WINDOW_MAXIMIZED)
+ (window-restored SDL_EVENT_WINDOW_RESTORED)
+ (window-mouse-enter SDL_EVENT_WINDOW_MOUSE_ENTER)
+ (window-mouse-leave SDL_EVENT_WINDOW_MOUSE_LEAVE)
+ (window-focus-gained SDL_EVENT_WINDOW_FOCUS_GAINED)
+ (window-focus-lost SDL_EVENT_WINDOW_FOCUS_LOST)
+ (window-close-requested SDL_EVENT_WINDOW_CLOSE_REQUESTED)
+ (window-hit-test SDL_EVENT_WINDOW_HIT_TEST)
+ (window-iccprof-changed SDL_EVENT_WINDOW_ICCPROF_CHANGED)
+ (window-display-changed SDL_EVENT_WINDOW_DISPLAY_CHANGED)
+ (window-display-scale-changed SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED)
+ (window-safe-area-changed SDL_EVENT_WINDOW_SAFE_AREA_CHANGED)
+ (window-occluded SDL_EVENT_WINDOW_OCCLUDED)
+ (window-enter-fullscreen SDL_EVENT_WINDOW_ENTER_FULLSCREEN)
+ (window-leave-fullscreen SDL_EVENT_WINDOW_LEAVE_FULLSCREEN)
+ (window-destroyed SDL_EVENT_WINDOW_DESTROYED)
+ (window-hdr-state-changed SDL_EVENT_WINDOW_HDR_STATE_CHANGED)
+ (key-down SDL_EVENT_KEY_DOWN #x300)
+ (key-up SDL_EVENT_KEY_UP)
+ (text-editing SDL_EVENT_TEXT_EDITING)
+ (text-input SDL_EVENT_TEXT_INPUT)
+ (keymap-changed SDL_EVENT_KEYMAP_CHANGED)
+ (keyboard-added SDL_EVENT_KEYBOARD_ADDED)
+ (keyboard-removed SDL_EVENT_KEYBOARD_REMOVED)
+ (text-editing-candidates SDL_EVENT_TEXT_EDITING_CANDIDATES)
+ (mouse-motion SDL_EVENT_MOUSE_MOTION #x400)
+ (mouse-button-down SDL_EVENT_MOUSE_BUTTON_DOWN)
+ (mouse-button-up SDL_EVENT_MOUSE_BUTTON_UP)
+ (mouse-wheel SDL_EVENT_MOUSE_WHEEL)
+ (mouse-added SDL_EVENT_MOUSE_ADDED)
+ (mouse-removed SDL_EVENT_MOUSE_REMOVED)
+ (joystick-axis-motion SDL_EVENT_JOYSTICK_AXIS_MOTION #x600)
+ (joystick-ball-motion SDL_EVENT_JOYSTICK_BALL_MOTION)
+ (joystick-hat-motion SDL_EVENT_JOYSTICK_HAT_MOTION)
+ (joystick-button-down SDL_EVENT_JOYSTICK_BUTTON_DOWN)
+ (joystick-button-up SDL_EVENT_JOYSTICK_BUTTON_UP)
+ (joystick-added SDL_EVENT_JOYSTICK_ADDED)
+ (joystick-removed SDL_EVENT_JOYSTICK_REMOVED)
+ (joystick-battery-updated SDL_EVENT_JOYSTICK_BATTERY_UPDATED)
+ (joystick-update-complete SDL_EVENT_JOYSTICK_UPDATE_COMPLETE)
+ (gamepad-axis-motion SDL_EVENT_GAMEPAD_AXIS_MOTION #x650)
+ (gamepad-button-down SDL_EVENT_GAMEPAD_BUTTON_DOWN)
+ (gamepad-button-up SDL_EVENT_GAMEPAD_BUTTON_UP)
+ (gamepad-added SDL_EVENT_GAMEPAD_ADDED)
+ (gamepad-removed SDL_EVENT_GAMEPAD_REMOVED)
+ (gamepad-remapped SDL_EVENT_GAMEPAD_REMAPPED)
+ (gamepad-touchpad-down SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN)
+ (gamepad-touchpad-motion SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION)
+ (gamepad-touchpad-up SDL_EVENT_GAMEPAD_TOUCHPAD_UP)
+ (gamepad-sensor-update SDL_EVENT_GAMEPAD_SENSOR_UPDATE)
+ (gamepad-update-complete SDL_EVENT_GAMEPAD_UPDATE_COMPLETE)
+ (gamepad-steam-handle-updated SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED)
+ (finger-down SDL_EVENT_FINGER_DOWN #x700)
+ (finger-up SDL_EVENT_FINGER_UP)
+ (finger-motion SDL_EVENT_FINGER_MOTION)
+ (clipboard-update SDL_EVENT_CLIPBOARD_UPDATE #x900)
+ (drop-file SDL_EVENT_DROP_FILE #x1000)
+ (drop-text SDL_EVENT_DROP_TEXT)
+ (drop-begin SDL_EVENT_DROP_BEGIN)
+ (drop-complete SDL_EVENT_DROP_COMPLETE)
+ (drop-position SDL_EVENT_DROP_POSITION)
+ (audio-device-added SDL_EVENT_AUDIO_DEVICE_ADDED #x1100)
+ (audio-device-removed SDL_EVENT_AUDIO_DEVICE_REMOVED)
+ (audio-device-format-changed SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)
+ (sensor-update SDL_EVENT_SENSOR_UPDATE #x1200)
+ (pen-proximity-in SDL_EVENT_PEN_PROXIMITY_IN #x1300)
+ (pen-proximity-out SDL_EVENT_PEN_PROXIMITY_OUT)
+ (pen-down SDL_EVENT_PEN_DOWN)
+ (pen-up SDL_EVENT_PEN_UP)
+ (pen-button-down SDL_EVENT_PEN_BUTTON_DOWN)
+ (pen-button-up SDL_EVENT_PEN_BUTTON_UP)
+ (pen-motion SDL_EVENT_PEN_MOTION)
+ (pen-axis SDL_EVENT_PEN_AXIS)
+ (camera-device-added SDL_EVENT_CAMERA_DEVICE_ADDED #x1400)
+ (camera-device-removed SDL_EVENT_CAMERA_DEVICE_REMOVED)
+ (camera-device-approved SDL_EVENT_CAMERA_DEVICE_APPROVED)
+ (camera-device-denied SDL_EVENT_CAMERA_DEVICE_DENIED)
+ (render-targets-reset SDL_EVENT_RENDER_TARGETS_RESET #x2000)
+ (render-device-reset SDL_EVENT_RENDER_DEVICE_RESET)
+ (poll-sentinel SDL_EVENT_POLL_SENTINEL #x7F00))
+
+(define SDL_EVENT_DISPLAY_FIRST SDL_EVENT_DISPLAY_ORIENTATION)
+(define SDL_EVENT_DISPLAY_LAST SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED)
+(define SDL_EVENT_WINDOW_FIRST SDL_EVENT_WINDOW_SHOWN)
+(define SDL_EVENT_WINDOW_LAST SDL_EVENT_WINDOW_HDR_STATE_CHANGED)
+(define SDL_EVENT_USER #x8000)
+(define SDL_EVENT_LAST #xFFFF)
+(define SDL_EVENT_ENUM_PADDING #x7FFFFFFF)
+
+(define-bstruct SDL_CommonEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)))
+
+(define-bstruct SDL_DisplayEvent
+ (struct
+ (type int) ; SDL_EventType
+ (reserved u32)
+ (timestamp u64)
+ (displayID u32) ; SDL_DisplayID
+ (data1 s32)
+ (data2 s32)))
+
+(define-bstruct SDL_WindowEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (data1 s32)
+ (data2 s32)))
+
+(define-bstruct SDL_KeyboardDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_KeyboardID
+ ))
+
+(define-bstruct SDL_KeyboardEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_KeyboardID
+ (scancode int) ; SDL_Scancode
+ (key int) ; SDL_Keycode
+ (mod u16) ; SDL_Keymod
+ (raw u16)
+ (down u8) ; bool
+ (repeat u8) ; bool
+ ))
+
+(define-bstruct SDL_TextEditingEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (text (* u8)) ; char*
+ (start s32)
+ (length s32)))
+
+(define-bstruct SDL_TextEditingCandidatesEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (candidates (* u8))
+ (num_candidates s32)
+ (selected_candidate s32)
+ (horizontal u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_TextInputEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (text (* u8))))
+
+(define-bstruct SDL_MouseDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_MouseID
+ ))
+
+(define-bstruct SDL_MouseMotionEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_MouseID
+ (state u32) ; SDL_MouseButtonFlags
+ (x f32)
+ (y f32)
+ (xrel f32)
+ (yrel f32)))
+
+(define-bstruct SDL_MouseButtonEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_MouseID
+ (button u8)
+ (down u8) ; bool
+ (clicks u8)
+ (_ u8)
+ (x f32)
+ (y f32)))
+
+(define-bstruct SDL_MouseWheelEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_MouseID
+ (x f32)
+ (y f32)
+ (direction int) ; SDL_MouseWheelDirection
+ (mouse_x f32)
+ (mouse_y f32)))
+
+(define-bstruct SDL_JoyAxisEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (axis u8)
+ (_ u8)
+ (_ u8)
+ (_ u8)
+ (value s16)
+ (_ u16)))
+
+(define-bstruct SDL_JoyBallEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (ball u8)
+ (_ u8)
+ (_ u8)
+ (_ u8)
+ (xrel s32)
+ (yrel s32)))
+
+(define-bstruct SDL_JoyHatEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (hat u8)
+ (value u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_JoyButtonEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (button u8)
+ (down u8) ; bool
+ (_ u8)
+ (_ u8)
+ ))
+
+(define-bstruct SDL_JoyDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ ))
+
+(define-bstruct SDL_JoyBatteryEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (state int) ; SDL_PowerState
+ (percent int)))
+
+(define-bstruct SDL_GamepadAxisEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (axis u8)
+ (_ u8)
+ (_ u8)
+ (_ u8)
+ (value s16)
+ (_ u16)))
+
+(define-bstruct SDL_GamepadButtonEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (button u8)
+ (down u8) ; bool
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GamepadDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ ))
+
+(define-bstruct SDL_GamepadTouchpadEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (touchpad s32)
+ (finger s32)
+ (x f32)
+ (y f32)
+ (pressure f32)))
+
+(define-bstruct SDL_GamepadSensorEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_JoystickID
+ (sensor s32)
+ (data (array 3 f32))
+ (sensor_timestamp u64)))
+
+(define-bstruct SDL_AudioDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_AudioDeviceID
+ (recording u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_CameraDeviceEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_CameraID
+ ))
+
+(define-bstruct SDL_TouchFingerEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (touchID u32) ; SDL_TouchID
+ (fingerID u32) ; SDL_FingerID
+ (x f32)
+ (y f32)
+ (dx f32)
+ (dy f32)
+ (pressure f32)
+ (windowID u32) ; SDL_WindowID
+ ))
+
+(define-bstruct SDL_PenProximityEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_PenID
+ ))
+
+(define-bstruct SDL_PenMotionEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_PenID
+ (pen_state u32) ; SDL_PenInputFlags
+ ))
+
+(define-bstruct SDL_PenTouchEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_PenID
+ (pen_state u32) ; SDL_PenInputFlags
+ (x f32)
+ (y f32)
+ (eraser u8) ; bool
+ (down u8) ; bool
+ ))
+
+(define-bstruct SDL_PenButtonEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_PenID
+ (pen_state u32) ; SDL_PenInputFlags
+ (x f32)
+ (y f32)
+ (button u8)
+ (down u8) ; bool
+ ))
+
+(define-bstruct SDL_PenAxisEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (which u32) ; SDL_PenID
+ (pen_state u32) ; SDL_PenInputFlags
+ (x f32)
+ (y f32)
+ (axis int) ; SDL_PenAxis
+ (value f32)))
+
+(define-bstruct SDL_DropEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (x f32)
+ (y f32)
+ (source (* u8)) ; char*
+ (data (* u8)) ; char*
+ ))
+
+(define-bstruct SDL_ClipboardEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)))
+
+(define-bstruct SDL_SensorEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (which u32) ; SDL_SensorID
+ (data (array 6 f32))
+ (sensor_timestamp u64)))
+
+(define-bstruct SDL_QuitEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)))
+
+(define-bstruct SDL_UserEvent
+ (struct
+ (type u32)
+ (reserved u32)
+ (timestamp u64)
+ (windowID u32) ; SDL_WindowID
+ (code s32)
+ (data1 (* void))
+ (data2 (* void))))
+
+(define-bstruct SDL_Event
+ (union
+ (type u32)
+ (common SDL_CommonEvent)
+ (display SDL_DisplayEvent)
+ (window SDL_WindowEvent)
+ (kdevice SDL_KeyboardDeviceEvent)
+ (key SDL_KeyboardEvent)
+ (edit SDL_TextEditingEvent)
+ (edit_candidates SDL_TextEditingCandidatesEvent)
+ (text SDL_TextInputEvent)
+ (mdevice SDL_MouseDeviceEvent)
+ (motion SDL_MouseMotionEvent)
+ (button SDL_MouseButtonEvent)
+ (wheel SDL_MouseWheelEvent)
+ (jdevice SDL_JoyDeviceEvent)
+ (jaxis SDL_JoyAxisEvent)
+ (jball SDL_JoyBallEvent)
+ (jhat SDL_JoyHatEvent)
+ (jbutton SDL_JoyButtonEvent)
+ (jbattery SDL_JoyBatteryEvent)
+ (gdevice SDL_GamepadDeviceEvent)
+ (gaxis SDL_GamepadAxisEvent)
+ (gbutton SDL_GamepadButtonEvent)
+ (gtouchpad SDL_GamepadTouchpadEvent)
+ (gsensor SDL_GamepadSensorEvent)
+ (adevice SDL_AudioDeviceEvent)
+ (cdevice SDL_CameraDeviceEvent)
+ (sensor SDL_SensorEvent)
+ (quit SDL_QuitEvent)
+ (user SDL_UserEvent)
+ (tfinger SDL_TouchFingerEvent)
+ (pproximity SDL_PenProximityEvent)
+ (ptouch SDL_PenTouchEvent)
+ (pmotion SDL_PenMotionEvent)
+ (pbutton SDL_PenButtonEvent)
+ (paxis SDL_PenAxisEvent)
+ (drop SDL_DropEvent)
+ (clipboard SDL_ClipboardEvent)
+ (_ (array 128 u8))))
+
+(define-sdl SDL_PumpEvents)
+;; SDL_PeepEvents
+(define-sdl SDL_HasEvent uint32 -> bool)
+(define-sdl SDL_HasEvents uint32 uint32 -> bool)
+(define-sdl SDL_FlushEvent uint32)
+(define-sdl SDL_FlushEvents uint32 uint32)
+(define-sdl SDL_PollEvent '* -> bool)
+(define-sdl SDL_WaitEvent '* -> bool)
+(define-sdl SDL_WaitEventTimeout '* int32 -> bool)
+(define-sdl SDL_PushEvent '* -> bool)
+;; SDL_SetEventFilter
+;; SDL_GetEventFilter
+;; SDL_AddEventWatch
+;; SDL_RemoveEventWatch
+;; SDL_FilterEvents
+;; SDL_SetEventEnabled
+;; SDL_EventEnabled
+;; SDL_RegisterEvents
+;; SDL_GetWindowFromEvent
diff --git a/sdl3/bindings/gpu.scm b/sdl3/bindings/gpu.scm
new file mode 100644
index 0000000..849e159
--- /dev/null
+++ b/sdl3/bindings/gpu.scm
@@ -0,0 +1,1190 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_gpu.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings gpu)
+ #:use-module (bstruct)
+ #:use-module (sdl3 bindings utils)
+ #:use-module (sdl3 bindings pixels)
+ #:use-module (sdl3 bindings surface)
+ #:use-module (system foreign)
+ #:export (SDL_GPUPrimitiveType
+ symbol->gpu-primitive-type
+ primitive-type->symbol
+ SDL_GPU_PRIMITIVETYPE_TRIANGLELIST
+ SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP
+ SDL_GPU_PRIMITIVETYPE_LINELIST
+ SDL_GPU_PRIMITIVETYPE_LINESTRIP
+ SDL_GPU_PRIMITIVETYPE_POINTLIST
+
+ SDL_GPULoadOp
+ symbol->gpu-load-op
+ gpu-load-op->symbol
+ SDL_GPU_LOADOP_LOAD
+ SDL_GPU_LOADOP_CLEAR
+ SDL_GPU_LOADOP_DONT_CARE
+
+ SDL_GPUStoreOp
+ symbol->gpu-store-op
+ gpu-store-op->symbol
+ SDL_GPU_STOREOP_STORE
+ SDL_GPU_STOREOP_DONT_CARE
+ SDL_GPU_STOREOP_RESOLVE
+ SDL_GPU_STOREOP_RESOLVE_AND_STORE
+
+ SDL_GPUIndexElementSize
+ symbol->gpu-index-element-size
+ gpu-index-element-size->symbol
+ SDL_GPU_INDEXELEMENTSIZE_16BIT
+ SDL_GPU_INDEXELEMENTSIZE_32BIT
+
+ SDL_GPUTextureFormat
+ symbol->gpu-texture-format
+ gpu-texture-format->symbol
+ SDL_GPU_TEXTUREFORMAT_INVALID
+ SDL_GPU_TEXTUREFORMAT_A8_UNORM
+ SDL_GPU_TEXTUREFORMAT_R8_UNORM
+ SDL_GPU_TEXTUREFORMAT_R8G8_UNORM
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM
+ SDL_GPU_TEXTUREFORMAT_R16_UNORM
+ SDL_GPU_TEXTUREFORMAT_R16G16_UNORM
+ SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM
+ SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM
+ SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM
+ SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM
+ SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM
+ SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM
+ SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT
+ SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT
+ SDL_GPU_TEXTUREFORMAT_R8_SNORM
+ SDL_GPU_TEXTUREFORMAT_R8G8_SNORM
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM
+ SDL_GPU_TEXTUREFORMAT_R16_SNORM
+ SDL_GPU_TEXTUREFORMAT_R16G16_SNORM
+ SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM
+ SDL_GPU_TEXTUREFORMAT_R16_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R32_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT
+ SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT
+ SDL_GPU_TEXTUREFORMAT_R8_UINT
+ SDL_GPU_TEXTUREFORMAT_R8G8_UINT
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT
+ SDL_GPU_TEXTUREFORMAT_R16_UINT
+ SDL_GPU_TEXTUREFORMAT_R16G16_UINT
+ SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT
+ SDL_GPU_TEXTUREFORMAT_R32_UINT
+ SDL_GPU_TEXTUREFORMAT_R32G32_UINT
+ SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT
+ SDL_GPU_TEXTUREFORMAT_R8_INT
+ SDL_GPU_TEXTUREFORMAT_R8G8_INT
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT
+ SDL_GPU_TEXTUREFORMAT_R16_INT
+ SDL_GPU_TEXTUREFORMAT_R16G16_INT
+ SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT
+ SDL_GPU_TEXTUREFORMAT_R32_INT
+ SDL_GPU_TEXTUREFORMAT_R32G32_INT
+ SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB
+ SDL_GPU_TEXTUREFORMAT_D16_UNORM
+ SDL_GPU_TEXTUREFORMAT_D24_UNORM
+ SDL_GPU_TEXTUREFORMAT_D32_FLOAT
+ SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT
+ SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT
+
+ SDL_GPUTextureUsageFlags
+ symbols->gpu-texture-usage-flags
+ gpu-texture-usage-flags->symbols
+ SDL_GPU_TEXTUREUSAGE_SAMPLER
+ SDL_GPU_TEXTUREUSAGE_COLOR_TARGET
+ SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET
+ SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ
+ SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ
+ SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE
+ SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE
+
+ SDL_GPUTextureType
+ symbol->gpu-texture-type
+ gpu-texture-type->symbol
+ SDL_GPU_TEXTURETYPE_2D
+ SDL_GPU_TEXTURETYPE_2D_ARRAY
+ SDL_GPU_TEXTURETYPE_3D
+ SDL_GPU_TEXTURETYPE_CUBE
+ SDL_GPU_TEXTURETYPE_CUBE_ARRAY
+
+ SDL_GPUSampleCount
+ int->gpu-sample-count
+ gpu-sample-count->int
+ SDL_GPU_SAMPLECOUNT_1
+ SDL_GPU_SAMPLECOUNT_2
+ SDL_GPU_SAMPLECOUNT_4
+ SDL_GPU_SAMPLECOUNT_8
+
+ SDL_GPUCubeMapFace
+ symbol->gpu-cube-map-face
+ gpu-cube-map-face->symbol
+ SDL_GPU_CUBEMAPFACE_POSITIVEX
+ SDL_GPU_CUBEMAPFACE_NEGATIVEX
+ SDL_GPU_CUBEMAPFACE_POSITIVEY
+ SDL_GPU_CUBEMAPFACE_NEGATIVEY
+ SDL_GPU_CUBEMAPFACE_POSITIVEZ
+ SDL_GPU_CUBEMAPFACE_NEGATIVEZ
+
+ SDL_GPUBufferUsageFlags
+ symbols->gpu-buffer-usage-flags
+ gpu-buffer-usage-flags->symbols
+ SDL_GPU_BUFFERUSAGE_VERTEX
+ SDL_GPU_BUFFERUSAGE_INDEX
+ SDL_GPU_BUFFERUSAGE_INDIRECT
+ SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ
+ SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ
+ SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE
+
+ SDL_GPUTransferBufferUsage
+ symbol->gpu-transfer-buffer-usage
+ gpu-transfer-buffer-usage->symbol
+ SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD
+ SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD
+
+ SDL_GPUShaderStage
+ symbol->gpu-shader-stage
+ gpu-shader-stage->symbol
+ SDL_GPU_SHADERSTAGE_VERTEX
+ SDL_GPU_SHADERSTAGE_FRAGMENT
+
+ SDL_GPUShaderFormat
+ symbols->gpu-shader-format
+ gpu-shader-format->symbols
+ SDL_GPU_SHADERFORMAT_INVALID
+ SDL_GPU_SHADERFORMAT_PRIVATE
+ SDL_GPU_SHADERFORMAT_SPIRV
+ SDL_GPU_SHADERFORMAT_DXBC
+ SDL_GPU_SHADERFORMAT_DXIL
+ SDL_GPU_SHADERFORMAT_MSL
+ SDL_GPU_SHADERFORMAT_METALLIB
+
+ SDL_GPUVertexElementFormat
+ symbol->gpu-vertex-element-format
+ gpu-vertex-element-format->symbol
+ SDL_GPU_VERTEXELEMENTFORMAT_INVALID
+ SDL_GPU_VERTEXELEMENTFORMAT_INT
+ SDL_GPU_VERTEXELEMENTFORMAT_INT2
+ SDL_GPU_VERTEXELEMENTFORMAT_INT3
+ SDL_GPU_VERTEXELEMENTFORMAT_INT4
+ SDL_GPU_VERTEXELEMENTFORMAT_UINT
+ SDL_GPU_VERTEXELEMENTFORMAT_UINT2
+ SDL_GPU_VERTEXELEMENTFORMAT_UINT3
+ SDL_GPU_VERTEXELEMENTFORMAT_UINT4
+ SDL_GPU_VERTEXELEMENTFORMAT_FLOAT
+ SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2
+ SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3
+ SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4
+ SDL_GPU_VERTEXELEMENTFORMAT_BYTE2
+ SDL_GPU_VERTEXELEMENTFORMAT_BYTE4
+ SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2
+ SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4
+ SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_SHORT2
+ SDL_GPU_VERTEXELEMENTFORMAT_SHORT4
+ SDL_GPU_VERTEXELEMENTFORMAT_USHORT2
+ SDL_GPU_VERTEXELEMENTFORMAT_USHORT4
+ SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM
+ SDL_GPU_VERTEXELEMENTFORMAT_HALF2
+ SDL_GPU_VERTEXELEMENTFORMAT_HALF4
+
+ SDL_GPUVertexInputRate
+ symbol->gpu-vertex-input-rate
+ gpu-vertex-input-rate->symbol
+ SDL_GPU_VERTEXINPUTRATE_VERTEX
+ SDL_GPU_VERTEXINPUTRATE_INSTANCE
+
+ SDL_GPUFillMode
+ symbol->gpu-fill-mode
+ gpu-fill-mode->symbol
+ SDL_GPU_FILLMODE_FILL
+ SDL_GPU_FILLMODE_LINE
+
+ SDL_GPUCullMode
+ symbol->gpu-cull-mode
+ gpu-cull-mode->symbol
+ SDL_GPU_CULLMODE_NONE
+ SDL_GPU_CULLMODE_FRONT
+ SDL_GPU_CULLMODE_BACK
+
+ SDL_GPUFrontFace
+ symbol->gpu-front-face
+ gpu-front-face->symbol
+ SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE
+ SDL_GPU_FRONTFACE_CLOCKWISE
+
+ SDL_GPUCompareOp
+ symbol->gpu-compare-op
+ gpu-compare-op->symbol
+ SDL_GPU_COMPAREOP_INVALID
+ SDL_GPU_COMPAREOP_NEVER
+ SDL_GPU_COMPAREOP_LESS
+ SDL_GPU_COMPAREOP_EQUAL
+ SDL_GPU_COMPAREOP_LESS_OR_EQUAL
+ SDL_GPU_COMPAREOP_GREATER
+ SDL_GPU_COMPAREOP_NOT_EQUAL
+ SDL_GPU_COMPAREOP_GREATER_OR_EQUAL
+ SDL_GPU_COMPAREOP_ALWAYS
+
+ SDL_GPUStencilOp
+ symbol->gpu-stencil-op
+ gpu-stencil-op->symbol
+ SDL_GPU_STENCILOP_INVALID
+ SDL_GPU_STENCILOP_KEEP
+ SDL_GPU_STENCILOP_ZERO
+ SDL_GPU_STENCILOP_REPLACE
+ SDL_GPU_STENCILOP_INCREMENT_AND_CLAMP
+ SDL_GPU_STENCILOP_DECREMENT_AND_CLAMP
+ SDL_GPU_STENCILOP_INVERT
+ SDL_GPU_STENCILOP_INCREMENT_AND_WRAP
+ SDL_GPU_STENCILOP_DECREMENT_AND_WRAP
+
+ SDL_GPUBlendOp
+ symbol->gpu-blend-op
+ gpu-blend-op->symbol
+ SDL_GPU_BLENDOP_INVALID
+ SDL_GPU_BLENDOP_ADD
+ SDL_GPU_BLENDOP_SUBTRACT
+ SDL_GPU_BLENDOP_REVERSE_SUBTRACT
+ SDL_GPU_BLENDOP_MIN
+ SDL_GPU_BLENDOP_MAX
+
+ SDL_GPUBlendFactor
+ symbol->gpu-blend-factor
+ gpu-blend-factor->symbol
+ SDL_GPU_BLENDFACTOR_INVALID
+ SDL_GPU_BLENDFACTOR_ZERO
+ SDL_GPU_BLENDFACTOR_ONE
+ SDL_GPU_BLENDFACTOR_SRC_COLOR
+ SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR
+ SDL_GPU_BLENDFACTOR_DST_COLOR
+ SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR
+ SDL_GPU_BLENDFACTOR_SRC_ALPHA
+ SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
+ SDL_GPU_BLENDFACTOR_DST_ALPHA
+ SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA
+ SDL_GPU_BLENDFACTOR_CONSTANT_COLOR
+ SDL_GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR
+ SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE
+
+ SDL_GPUColorComponentFlags
+ symbols->gpu-color-component-flags
+ gpu-color-component-flags->symbols
+ SDL_GPU_COLORCOMPONENT_R
+ SDL_GPU_COLORCOMPONENT_G
+ SDL_GPU_COLORCOMPONENT_B
+ SDL_GPU_COLORCOMPONENT_A
+
+ SDL_GPUFilter
+ symbol->gpu-filter
+ gpu-filter->symbol
+ SDL_GPU_FILTER_NEAREST
+ SDL_GPU_FILTER_LINEAR
+
+ SDL_GPUSamplerMipmapMode
+ symbol->gpu-sampler-mipmap-mode
+ gpu-sampler-mipmap-mode->symbol
+ SDL_GPU_SAMPLERMIPMAPMODE_NEAREST
+ SDL_GPU_SAMPLERMIPMAPMODE_LINEAR
+
+ SDL_GPUSamplerAddressMode
+ symbol->gpu-sampler-address-mode
+ gpu-sampler-address-mode->symbol
+ SDL_GPU_SAMPLERADDRESSMODE_REPEAT
+ SDL_GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT
+ SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE
+
+ SDL_GPUPresentMode
+ symbol->gpu-present-mode
+ gpu-present-mode->symbol
+ SDL_GPU_PRESENTMODE_VSYNC
+ SDL_GPU_PRESENTMODE_IMMEDIATE
+ SDL_GPU_PRESENTMODE_MAILBOX
+
+ SDL_GPUSwapchainComposition
+ symbol->gpu-swapchain-composition
+ gpu-swapchain-composition->symbol
+ SDL_GPU_SWAPCHAINCOMPOSITION_SDR
+ SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR
+ SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR
+ SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048
+
+ SDL_GPUViewport
+ SDL_GPUTextureTransferInfo
+ SDL_GPUTransferBufferLocation
+ SDL_GPUTextureLocation
+ SDL_GPUTextureRegion
+ SDL_GPUBlitRegion
+ SDL_GPUBufferLocation
+ SDL_GPUBufferRegion
+ SDL_GPUVertexBufferDescription
+ SDL_GPUVertexAttribute
+ SDL_GPUVertexInputState
+ SDL_GPUStencilOpState
+ SDL_GPUColorTargetBlendState
+ SDL_GPUShaderCreateInfo
+ SDL_GPUTextureCreateInfo
+ SDL_GPUBufferCreateInfo
+ SDL_GPUTransferBufferCreateInfo
+ SDL_GPURasterizerState
+ SDL_GPUMultisampleState
+ SDL_GPUDepthStencilState
+ SDL_GPUColorTargetDescription
+ SDL_GPUGraphicsPipelineTargetInfo
+ SDL_GPUGraphicsPipelineCreateInfo
+ SDL_GPUComputePipelineCreateInfo
+ SDL_GPUColorTargetInfo
+ SDL_GPUDepthStencilTargetInfo
+ SDL_GPUBlitInfo
+ SDL_GPUBufferBinding
+ SDL_GPUTextureSamplerBinding
+ SDL_GPUStorageBufferReadWriteBinding
+ SDL_GPUStorageTextureReadWriteBinding
+
+ gpu-device?
+ wrap-gpu-device
+ unwrap-gpu-device
+ gpu-device-destroyed?
+ set-gpu-device-destroyed!
+
+ gpu-buffer?
+ wrap-gpu-buffer
+ unwrap-gpu-buffer
+ gpu-buffer-released?
+ set-gpu-buffer-released!
+
+ gpu-transfer-buffer?
+ wrap-gpu-transfer-buffer
+ unwrap-gpu-transfer-buffer
+ gpu-transfer-buffer-released?
+ set-gpu-transfer-buffer-released!
+
+ gpu-shader?
+ wrap-gpu-shader
+ unwrap-gpu-shader
+ gpu-shader-released?
+ set-gpu-shader-released!
+
+ gpu-texture?
+ wrap-gpu-texture
+ unwrap-gpu-texture
+ gpu-texture-released?
+ set-gpu-texture-released!
+
+ gpu-graphics-pipeline?
+ wrap-gpu-graphics-pipeline
+ unwrap-gpu-graphics-pipeline
+ gpu-graphics-pipeline-released?
+ set-gpu-graphics-pipeline-released!
+
+ gpu-command-buffer?
+ wrap-gpu-command-buffer
+ unwrap-gpu-command-buffer
+
+ gpu-copy-pass?
+ wrap-gpu-copy-pass
+ unwrap-gpu-copy-pass
+
+ gpu-render-pass?
+ wrap-gpu-render-pass
+ unwrap-gpu-render-pass
+
+ gpu-compute-pass?
+ wrap-gpu-compute-pass
+ unwrap-gpu-compute-pass
+
+ SDL_AcquireGPUCommandBuffer
+ SDL_AcquireGPUSwapchainTexture
+ SDL_BeginGPUCopyPass
+ SDL_BeginGPURenderPass
+ SDL_BindGPUGraphicsPipeline
+ SDL_BindGPUVertexBuffers
+ SDL_BlitGPUTexture
+ SDL_CreateGPUBuffer
+ SDL_CreateGPUDevice
+ SDL_CreateGPUGraphicsPipeline
+ SDL_CreateGPUShader
+ SDL_CreateGPUTexture
+ SDL_CreateGPUTransferBuffer
+ SDL_ClaimWindowForGPUDevice
+ SDL_DestroyGPUDevice
+ SDL_DrawGPUPrimitives
+ SDL_EndGPUCopyPass
+ SDL_EndGPURenderPass
+ SDL_GetGPUDeviceDriver
+ SDL_GetGPUDriver
+ SDL_GetGPUSwapchainTextureFormat
+ SDL_GetNumGPUDrivers
+ SDL_GPUTextureSupportsSampleCount
+ SDL_MapGPUTransferBuffer
+ SDL_PushGPUVertexUniformData
+ SDL_PushGPUFragmentUniformData
+ SDL_ReleaseGPUBuffer
+ SDL_ReleaseGPUGraphicsPipeline
+ SDL_ReleaseGPUShader
+ SDL_ReleaseGPUTexture
+ SDL_ReleaseGPUTransferBuffer
+ SDL_ReleaseWindowFromGPUDevice
+ SDL_SetGPUBufferName
+ SDL_SubmitGPUCommandBuffer
+ SDL_UnmapGPUTransferBuffer
+ SDL_UploadToGPUBuffer))
+
+(define-enum SDL_GPUPrimitiveType
+ symbol->gpu-primitive-type
+ primitive-type->symbol
+ (triangle-list SDL_GPU_PRIMITIVETYPE_TRIANGLELIST)
+ (triangle-strip SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP)
+ (line-list SDL_GPU_PRIMITIVETYPE_LINELIST)
+ (line-strip SDL_GPU_PRIMITIVETYPE_LINESTRIP)
+ (point-list SDL_GPU_PRIMITIVETYPE_POINTLIST))
+
+(define-enum SDL_GPULoadOp
+ symbol->gpu-load-op
+ gpu-load-op->symbol
+ (load SDL_GPU_LOADOP_LOAD)
+ (clear SDL_GPU_LOADOP_CLEAR)
+ (dont-care SDL_GPU_LOADOP_DONT_CARE))
+
+(define-enum SDL_GPUStoreOp
+ symbol->gpu-store-op
+ gpu-store-op->symbol
+ (store SDL_GPU_STOREOP_STORE)
+ (dont-care SDL_GPU_STOREOP_DONT_CARE)
+ (resolve SDL_GPU_STOREOP_RESOLVE)
+ (resolve-and-store SDL_GPU_STOREOP_RESOLVE_AND_STORE))
+
+(define-enum SDL_GPUIndexElementSize
+ symbol->gpu-index-element-size
+ gpu-index-element-size->symbol
+ (16-bit SDL_GPU_INDEXELEMENTSIZE_16BIT)
+ (32-bit SDL_GPU_INDEXELEMENTSIZE_32BIT))
+
+(define-enum SDL_GPUTextureFormat
+ symbol->gpu-texture-format
+ gpu-texture-format->symbol
+ (invalid SDL_GPU_TEXTUREFORMAT_INVALID)
+ (a8-unorm SDL_GPU_TEXTUREFORMAT_A8_UNORM)
+ (r8-unorm SDL_GPU_TEXTUREFORMAT_R8_UNORM)
+ (r8g8-unorm SDL_GPU_TEXTUREFORMAT_R8G8_UNORM)
+ (r8g8b8a8-unorm SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM)
+ (r16-unorm SDL_GPU_TEXTUREFORMAT_R16_UNORM)
+ (r16g16-unorm SDL_GPU_TEXTUREFORMAT_R16G16_UNORM)
+ (r16g16b16a16-unorm SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM)
+ (r10g10b10a2-unorm SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM)
+ (b5g6r5-unorm SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM)
+ (b5g5r5a1-unorm SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM)
+ (b4g4r4a4-unorm SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM)
+ (b8g8r8a8-unorm SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM)
+ (bc1-rbga-unorm SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM)
+ (bc2-rgba-unorm SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM)
+ (bc3-rgba-unorm SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM)
+ (bc4-r-unorm SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM)
+ (bc5-rg-unorm SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM)
+ (bc7-rgba-unorm SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM)
+ (bc6h-rgb-float SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT)
+ (bc6h-rgb-float SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT)
+ (r8-snorm SDL_GPU_TEXTUREFORMAT_R8_SNORM)
+ (r8g8-snorm SDL_GPU_TEXTUREFORMAT_R8G8_SNORM)
+ (r8g8b8a8-snorm SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM)
+ (r16-snorm SDL_GPU_TEXTUREFORMAT_R16_SNORM)
+ (r16g16-snorm SDL_GPU_TEXTUREFORMAT_R16G16_SNORM)
+ (r16g16b16a16-snorm SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM)
+ (r16-float SDL_GPU_TEXTUREFORMAT_R16_FLOAT)
+ (r16g16-float SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT)
+ (r16g16b16a16-float SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT)
+ (r32-float SDL_GPU_TEXTUREFORMAT_R32_FLOAT)
+ (r32g32-float SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT)
+ (r32g32b32a32-float SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT)
+ (r11g11b10-ufloat SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT)
+ (r8-uint SDL_GPU_TEXTUREFORMAT_R8_UINT)
+ (r8g8-uint SDL_GPU_TEXTUREFORMAT_R8G8_UINT)
+ (r8g8b8a8-uint SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT)
+ (r16-uint SDL_GPU_TEXTUREFORMAT_R16_UINT)
+ (r16g16-uint SDL_GPU_TEXTUREFORMAT_R16G16_UINT)
+ (r16g16b16a16-uint SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT)
+ (r32-uint SDL_GPU_TEXTUREFORMAT_R32_UINT)
+ (r32g32-uint SDL_GPU_TEXTUREFORMAT_R32G32_UINT)
+ (r32g32b32a32-uint SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT)
+ (r8-int SDL_GPU_TEXTUREFORMAT_R8_INT)
+ (r8g8-int SDL_GPU_TEXTUREFORMAT_R8G8_INT)
+ (r8g8b8a8-int SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT)
+ (r16-int SDL_GPU_TEXTUREFORMAT_R16_INT)
+ (r16g16-int SDL_GPU_TEXTUREFORMAT_R16G16_INT)
+ (r16g16b16a16-int SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT)
+ (r32-int SDL_GPU_TEXTUREFORMAT_R32_INT)
+ (r32g32-int SDL_GPU_TEXTUREFORMAT_R32G32_INT)
+ (r32g32b32a32-int SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT)
+ (r8g8b8a8-unorm-srgb SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB)
+ (b8g8r8a8-unorm-srgb SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB)
+ (bc1-unorm-srgb SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB)
+ (bc2-unorm-srgb SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB)
+ (bc3-unorm-srgb SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB)
+ (bc7-unorm-srgb SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB)
+ (d16-unorm SDL_GPU_TEXTUREFORMAT_D16_UNORM)
+ (d24-unorm SDL_GPU_TEXTUREFORMAT_D24_UNORM)
+ (d32-float SDL_GPU_TEXTUREFORMAT_D32_FLOAT)
+ (d24-unorm-s8-uint SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT)
+ (d32-float-s8-uint SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT))
+
+(define-bitmask (SDL_GPUTextureUsageFlags uint32)
+ symbols->gpu-texture-usage-flags
+ gpu-texture-usage-flags->symbols
+ (sampler SDL_GPU_TEXTUREUSAGE_SAMPLER)
+ (color-target SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)
+ (depth-stencil-target SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)
+ (graphics-storage-read SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ)
+ (compute-storage-read SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)
+ (compute-storage-write SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE)
+ (compute-storage-simultaneous-read-write
+ SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE))
+
+(define-enum SDL_GPUTextureType
+ symbol->gpu-texture-type
+ gpu-texture-type->symbol
+ (2d SDL_GPU_TEXTURETYPE_2D)
+ (2d-array SDL_GPU_TEXTURETYPE_2D_ARRAY)
+ (3d SDL_GPU_TEXTURETYPE_3D)
+ (cube SDL_GPU_TEXTURETYPE_CUBE)
+ (cube-array SDL_GPU_TEXTURETYPE_CUBE_ARRAY))
+
+(define-enum SDL_GPUSampleCount
+ int->gpu-sample-count
+ gpu-sample-count->int
+ (1 SDL_GPU_SAMPLECOUNT_1)
+ (2 SDL_GPU_SAMPLECOUNT_2)
+ (4 SDL_GPU_SAMPLECOUNT_4)
+ (8 SDL_GPU_SAMPLECOUNT_8))
+
+(define-enum SDL_GPUCubeMapFace
+ symbol->gpu-cube-map-face
+ gpu-cube-map-face->symbol
+ (positive-x SDL_GPU_CUBEMAPFACE_POSITIVEX)
+ (negative-x SDL_GPU_CUBEMAPFACE_NEGATIVEX)
+ (positive-y SDL_GPU_CUBEMAPFACE_POSITIVEY)
+ (negative-y SDL_GPU_CUBEMAPFACE_NEGATIVEY)
+ (positive-z SDL_GPU_CUBEMAPFACE_POSITIVEZ)
+ (negative-z SDL_GPU_CUBEMAPFACE_NEGATIVEZ))
+
+(define-bitmask (SDL_GPUBufferUsageFlags uint32)
+ symbols->gpu-buffer-usage-flags
+ gpu-buffer-usage-flags->symbols
+ (vertex SDL_GPU_BUFFERUSAGE_VERTEX)
+ (index SDL_GPU_BUFFERUSAGE_INDEX)
+ (indirect SDL_GPU_BUFFERUSAGE_INDIRECT)
+ (graphics-storage-read SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ)
+ (compute-storage-read SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ)
+ (compute-storage-write SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE))
+
+(define-enum SDL_GPUTransferBufferUsage
+ symbol->gpu-transfer-buffer-usage
+ gpu-transfer-buffer-usage->symbol
+ (upload SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD)
+ (download SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD))
+
+(define-enum SDL_GPUShaderStage
+ symbol->gpu-shader-stage
+ gpu-shader-stage->symbol
+ (vertex SDL_GPU_SHADERSTAGE_VERTEX)
+ (fragment SDL_GPU_SHADERSTAGE_FRAGMENT))
+
+(define-bitmask (SDL_GPUShaderFormat uint32)
+ symbols->gpu-shader-format
+ gpu-shader-format->symbols
+ (private SDL_GPU_SHADERFORMAT_PRIVATE)
+ (spirv SDL_GPU_SHADERFORMAT_SPIRV)
+ (dxbc SDL_GPU_SHADERFORMAT_DXBC)
+ (dxil SDL_GPU_SHADERFORMAT_DXIL)
+ (msl SDL_GPU_SHADERFORMAT_MSL)
+ (metallib SDL_GPU_SHADERFORMAT_METALLIB))
+(define SDL_GPU_SHADERFORMAT_INVALID 0)
+
+(define-enum SDL_GPUVertexElementFormat
+ symbol->gpu-vertex-element-format
+ gpu-vertex-element-format->symbol
+ (invalid SDL_GPU_VERTEXELEMENTFORMAT_INVALID)
+ (int SDL_GPU_VERTEXELEMENTFORMAT_INT)
+ (int2 SDL_GPU_VERTEXELEMENTFORMAT_INT2)
+ (int3 SDL_GPU_VERTEXELEMENTFORMAT_INT3)
+ (int4 SDL_GPU_VERTEXELEMENTFORMAT_INT4)
+ (uint SDL_GPU_VERTEXELEMENTFORMAT_UINT)
+ (uint2 SDL_GPU_VERTEXELEMENTFORMAT_UINT2)
+ (uint3 SDL_GPU_VERTEXELEMENTFORMAT_UINT3)
+ (uint4 SDL_GPU_VERTEXELEMENTFORMAT_UINT4)
+ (float SDL_GPU_VERTEXELEMENTFORMAT_FLOAT)
+ (float2 SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2)
+ (float3 SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3)
+ (float4 SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4)
+ (byte2 SDL_GPU_VERTEXELEMENTFORMAT_BYTE2)
+ (byte4 SDL_GPU_VERTEXELEMENTFORMAT_BYTE4)
+ (ubyte2 SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2)
+ (ubyte4 SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4)
+ (byte2-norm SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM)
+ (byte4-norm SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM)
+ (ubyte2-norm SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM)
+ (ubyte4-norm SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM)
+ (short2 SDL_GPU_VERTEXELEMENTFORMAT_SHORT2)
+ (short4 SDL_GPU_VERTEXELEMENTFORMAT_SHORT4)
+ (ushort2 SDL_GPU_VERTEXELEMENTFORMAT_USHORT2)
+ (ushort4 SDL_GPU_VERTEXELEMENTFORMAT_USHORT4)
+ (short2-norm SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM)
+ (short4-norm SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM)
+ (ushort2-norm SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM)
+ (ushort4-norm SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM)
+ (half2 SDL_GPU_VERTEXELEMENTFORMAT_HALF2)
+ (half4 SDL_GPU_VERTEXELEMENTFORMAT_HALF4))
+
+(define-enum SDL_GPUVertexInputRate
+ symbol->gpu-vertex-input-rate
+ gpu-vertex-input-rate->symbol
+ (vertex SDL_GPU_VERTEXINPUTRATE_VERTEX)
+ (instance SDL_GPU_VERTEXINPUTRATE_INSTANCE))
+
+(define-enum SDL_GPUFillMode
+ symbol->gpu-fill-mode
+ gpu-fill-mode->symbol
+ (fill SDL_GPU_FILLMODE_FILL)
+ (line SDL_GPU_FILLMODE_LINE))
+
+(define-enum SDL_GPUCullMode
+ symbol->gpu-cull-mode
+ gpu-cull-mode->symbol
+ (none SDL_GPU_CULLMODE_NONE)
+ (front SDL_GPU_CULLMODE_FRONT)
+ (back SDL_GPU_CULLMODE_BACK))
+
+(define-enum SDL_GPUFrontFace
+ symbol->gpu-front-face
+ gpu-front-face->symbol
+ (counter-clockwise SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE)
+ (clockwise SDL_GPU_FRONTFACE_CLOCKWISE))
+
+(define-enum SDL_GPUCompareOp
+ symbol->gpu-compare-op
+ gpu-compare-op->symbol
+ (invalid SDL_GPU_COMPAREOP_INVALID)
+ (never SDL_GPU_COMPAREOP_NEVER)
+ (less SDL_GPU_COMPAREOP_LESS)
+ (equal SDL_GPU_COMPAREOP_EQUAL)
+ (less-or-equal SDL_GPU_COMPAREOP_LESS_OR_EQUAL)
+ (greater SDL_GPU_COMPAREOP_GREATER)
+ (not-equal SDL_GPU_COMPAREOP_NOT_EQUAL)
+ (greater-or-equal SDL_GPU_COMPAREOP_GREATER_OR_EQUAL)
+ (always SDL_GPU_COMPAREOP_ALWAYS))
+
+(define-enum SDL_GPUStencilOp
+ symbol->gpu-stencil-op
+ gpu-stencil-op->symbol
+ (invalid SDL_GPU_STENCILOP_INVALID)
+ (keep SDL_GPU_STENCILOP_KEEP)
+ (zero SDL_GPU_STENCILOP_ZERO)
+ (replace SDL_GPU_STENCILOP_REPLACE)
+ (increment-and-clamp SDL_GPU_STENCILOP_INCREMENT_AND_CLAMP)
+ (decrement-and-clamp SDL_GPU_STENCILOP_DECREMENT_AND_CLAMP)
+ (invert SDL_GPU_STENCILOP_INVERT)
+ (increment-and-wrap SDL_GPU_STENCILOP_INCREMENT_AND_WRAP)
+ (decrement-and-wrap SDL_GPU_STENCILOP_DECREMENT_AND_WRAP))
+
+(define-enum SDL_GPUBlendOp
+ symbol->gpu-blend-op
+ gpu-blend-op->symbol
+ (invalid SDL_GPU_BLENDOP_INVALID)
+ (add SDL_GPU_BLENDOP_ADD)
+ (subtract SDL_GPU_BLENDOP_SUBTRACT)
+ (reverse-subtract SDL_GPU_BLENDOP_REVERSE_SUBTRACT)
+ (min SDL_GPU_BLENDOP_MIN)
+ (max SDL_GPU_BLENDOP_MAX))
+
+(define-enum SDL_GPUBlendFactor
+ symbol->gpu-blend-factor
+ gpu-blend-factor->symbol
+ (invalid SDL_GPU_BLENDFACTOR_INVALID)
+ (zero SDL_GPU_BLENDFACTOR_ZERO)
+ (one SDL_GPU_BLENDFACTOR_ONE)
+ (src-color SDL_GPU_BLENDFACTOR_SRC_COLOR)
+ (one-minus-src-color SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR)
+ (dst-color SDL_GPU_BLENDFACTOR_DST_COLOR)
+ (one-minus-dst-color SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR)
+ (src-alpha SDL_GPU_BLENDFACTOR_SRC_ALPHA)
+ (one-minus-src-alpha SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA)
+ (dst-alpha SDL_GPU_BLENDFACTOR_DST_ALPHA)
+ (one-minus-dst-alpha SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA)
+ (constant-color SDL_GPU_BLENDFACTOR_CONSTANT_COLOR)
+ (one-minus-constant-color SDL_GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR)
+ (alpha-saturate SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE))
+
+(define-bitmask (SDL_GPUColorComponentFlags uint8)
+ symbols->gpu-color-component-flags
+ gpu-color-component-flags->symbols
+ (r SDL_GPU_COLORCOMPONENT_R)
+ (g SDL_GPU_COLORCOMPONENT_G)
+ (b SDL_GPU_COLORCOMPONENT_B)
+ (a SDL_GPU_COLORCOMPONENT_A))
+
+(define-enum SDL_GPUFilter
+ symbol->gpu-filter
+ gpu-filter->symbol
+ (nearest SDL_GPU_FILTER_NEAREST)
+ (linear SDL_GPU_FILTER_LINEAR))
+
+(define-enum SDL_GPUSamplerMipmapMode
+ symbol->gpu-sampler-mipmap-mode
+ gpu-sampler-mipmap-mode->symbol
+ (nearest SDL_GPU_SAMPLERMIPMAPMODE_NEAREST)
+ (linear SDL_GPU_SAMPLERMIPMAPMODE_LINEAR))
+
+(define-enum SDL_GPUSamplerAddressMode
+ symbol->gpu-sampler-address-mode
+ gpu-sampler-address-mode->symbol
+ (repease SDL_GPU_SAMPLERADDRESSMODE_REPEAT)
+ (mirrored-repeat SDL_GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT)
+ (clamp-to-edge SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE))
+
+(define-enum SDL_GPUPresentMode
+ symbol->gpu-present-mode
+ gpu-present-mode->symbol
+ (vsync SDL_GPU_PRESENTMODE_VSYNC)
+ (immediate SDL_GPU_PRESENTMODE_IMMEDIATE)
+ (mailbox SDL_GPU_PRESENTMODE_MAILBOX))
+
+(define-enum SDL_GPUSwapchainComposition
+ symbol->gpu-swapchain-composition
+ gpu-swapchain-composition->symbol
+ (sdr SDL_GPU_SWAPCHAINCOMPOSITION_SDR)
+ (sdr-linear SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR)
+ (hdr-extended-linear SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR)
+ (hdr10-st2048 SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048))
+
+(define-bstruct SDL_GPUViewport
+ (struct
+ (x f32)
+ (y f32)
+ (w f32)
+ (h f32)
+ (min_depth f32)
+ (max_depth f32)))
+
+(define-bstruct SDL_GPUTextureTransferInfo
+ (struct
+ (transfer_buffer (* void)) ; SDL_GPUTransferBuffer
+ (offset u32)
+ (pixels_per_row u32)
+ (rows_per_layer u32)))
+
+(define-bstruct SDL_GPUTransferBufferLocation
+ (struct
+ (transfer_buffer (* void)) ; SDL_GPUTransferBuffer
+ (offset u32)))
+
+(define-bstruct SDL_GPUTextureLocation
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (mip_level u32)
+ (layer u32)
+ (x u32)
+ (y u32)
+ (z u32)))
+
+(define-bstruct SDL_GPUTextureRegion
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (mip_level u32)
+ (layer u32)
+ (x u32)
+ (y u32)
+ (z u32)
+ (w u32)
+ (h u32)
+ (d u32)))
+
+(define-bstruct SDL_GPUBlitRegion
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (mip_level u32)
+ (layer_or_depth_plane u32)
+ (x u32)
+ (y u32)
+ (w u32)
+ (h u32)))
+
+(define-bstruct SDL_GPUBufferLocation
+ (struct
+ (buffer (* void)) ; SDL_GPUBuffer
+ (offset u32)))
+
+(define-bstruct SDL_GPUBufferRegion
+ (struct
+ (buffer (* void)) ; SDL_GPUBuffer
+ (offset u32)
+ (size u32)))
+
+(define-bstruct SDL_GPUVertexBufferDescription
+ (struct
+ (slot u32)
+ (pitch u32)
+ (input_rate int) ; SDL_GPUVertexInputRate
+ (instance_step_rate u32)))
+
+(define-bstruct SDL_GPUVertexAttribute
+ (struct
+ (location u32)
+ (buffer_slot u32)
+ (format int) ; SDL_GPUVertexElementFormat
+ (offset u32)))
+
+(define-bstruct SDL_GPUVertexInputState
+ (struct
+ (vertex_buffer_descriptions (* SDL_GPUVertexBufferDescription))
+ (num_vertex_buffers u32)
+ (vertex_attributes (* SDL_GPUVertexAttribute))
+ (num_vertex_attributes u32)))
+
+(define-bstruct SDL_GPUStencilOpState
+ (struct
+ (fail_op int) ; SDL_GPUStencilOp
+ (pass_op int) ; SDL_GPUStencilOp
+ (depth_fail_op int) ; SDL_GPUStencilOp
+ (compare_op int) ; SDL_GPUCompareOp
+ ))
+
+(define-bstruct SDL_GPUColorTargetBlendState
+ (struct
+ (src_color_blendfactor int) ; SDL_GPUBlendFactor
+ (dst_color_blendfactor int) ; SDL_GPUBlendFactor
+ (color_blend_op int) ; SDL_GPUBlendOp
+ (src_alpha_blendfactor int) ; SDL_GPUBlendFactor
+ (dst_alpha_blendfactor int) ; SDL_GPUBlendFactor
+ (alpha_blend_op int) ; SDL_GPUBlendOp
+ (color_write_mask u8) ; SDL_GPUColorComponentFlags
+ (enable_blend u8) ; bool
+ (enable_color_write_mask u8) ; bool
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUShaderCreateInfo
+ (struct
+ (code_size size_t)
+ (code (* u8))
+ (entrypoint (* u8)) ; char*
+ (format u32) ; SDL_GPUShaderFormat
+ (stage int) ; SDL_GPUShaderStage
+ (num_samplers u32)
+ (num_storage_textures u32)
+ (num_storage_buffers u32)
+ (num_uniform_buffers u32)
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPUTextureCreateInfo
+ (struct
+ (type int) ; SDL_GPUTextureType
+ (format int) ; SDL_GPUTextureFormat
+ (usage u32) ; SDL_GPUTextureUsageFlags
+ (width u32)
+ (height u32)
+ (layer_count_or_depth u32)
+ (num_levels u32)
+ (sample_count int) ; SDL_GPUSampleCount
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPUBufferCreateInfo
+ (struct
+ (usage u32) ; SDL_GPUBufferUsageFlags
+ (size u32)
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPUTransferBufferCreateInfo
+ (struct
+ (usage u32) ; SDL_GPUTransferBufferUsage
+ (size u32)
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPURasterizerState
+ (struct
+ (fill_mode int) ; SDL_GPUFillMode
+ (cull_mode int) ; SDL_GPUCullMode
+ (front_face int) ; SDL_GPUFrontFace
+ (depth_bias_constant_factor f32)
+ (depth_bias_clamp f32)
+ (depth_bias_slope_factor f32)
+ (enable_depth_bias u8) ; bool
+ (enable_depth_clip u8) ; bool
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUMultisampleState
+ (struct
+ (sample_count int) ; SDL_GPUSampleCount
+ (sample_mask u32)
+ (enable_mask u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUDepthStencilState
+ (struct
+ (compare_op u32) ; SDL_GPUCompareOp
+ (back_stencil_state SDL_GPUStencilOpState)
+ (front_stencil_state SDL_GPUStencilOpState)
+ (compare_mask u8)
+ (write_mask u8)
+ (enable_depth_test u8) ; bool
+ (enable_depth_write u8) ; bool
+ (enable_stencil_test u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUColorTargetDescription
+ (struct
+ (format u32) ; SDL_GPUTextureFormat
+ (blend_state SDL_GPUColorTargetBlendState)))
+
+(define-bstruct SDL_GPUGraphicsPipelineTargetInfo
+ (struct
+ (color_target_descriptions (* SDL_GPUColorTargetDescription))
+ (num_color_targets u32)
+ (depth_stencil_format u32) ; SDL_GPUTextureFormat
+ (has_depth_stencil_target u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUGraphicsPipelineCreateInfo
+ (struct
+ (vertex_shader (* void)) ; SDL_GPUShader
+ (fragment_shader (* void)) ; SDL_GPUShader
+ (vertex_input_state SDL_GPUVertexInputState)
+ (primitive_type int) ; SDL_GPUPrimitiveType
+ (rasterizer_state SDL_GPURasterizerState)
+ (multisample_state SDL_GPUMultisampleState)
+ (depth_stencil_state SDL_GPUDepthStencilState)
+ (target_info SDL_GPUGraphicsPipelineTargetInfo)
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPUComputePipelineCreateInfo
+ (struct
+ (code_size size_t)
+ (code (* u8))
+ (entrypoint (* u8)) ; char
+ (format int) ; SDL_GPUShaderFormat
+ (num_samplers u32)
+ (num_readonly_storage_textures u32)
+ (num_readonly_storage_buffers u32)
+ (num_readwrite_storage_textures u32)
+ (num_readwrite_storage_buffers u32)
+ (num_uniform_buffers u32)
+ (threadcount_x u32)
+ (threadcount_y u32)
+ (threadcount_z u32)
+ (props u32) ; SDL_PropertiesID
+ ))
+
+(define-bstruct SDL_GPUColorTargetInfo
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (mip_level u32)
+ (layer_or_depth_plane u32)
+ (clear_color SDL_FColor)
+ (load_op int) ; SDL_GPULoadOp
+ (store_op int) ; SDL_GPUStoreOp
+ (resolve_texture (* void)) ; SDL_GPUTexture
+ (resolve_mip_level u32)
+ (resolve_layer u32)
+ (cycle u8) ; bool
+ (cycle_resolve_texture u8) ; bool
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUDepthStencilTargetInfo
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (clear_depth f32)
+ (load_op int) ; SDL_GPULoadOp
+ (store_op int) ; SDL_GPUStoreOp
+ (stencil_load_op int) ; SDL_GPULoadOp
+ (stencil_store_op int) ; SDL_GPUStoreOp
+ (cycle u8) ; bool
+ (clear_stencil u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUBlitInfo
+ (struct
+ (source SDL_GPUBlitRegion)
+ (destination SDL_GPUBlitRegion)
+ (load_op int) ; SDL_GPULoadOp
+ (clear_color SDL_FColor)
+ (flip_mode int) ; SDL_FlipMode
+ (filter int) ; SDL_GPUFilter
+ (cycle u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUBufferBinding
+ (struct
+ (buffer (* void)) ; SDL_GPUBuffer
+ (offset u32)))
+
+(define-bstruct SDL_GPUTextureSamplerBinding
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (sampler (* void)) ; SDL_GPUSampler
+ ))
+
+(define-bstruct SDL_GPUStorageBufferReadWriteBinding
+ (struct
+ (buffer (* void)) ; SDL_GPUBuffer
+ (cycle u8) ; bool
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-bstruct SDL_GPUStorageTextureReadWriteBinding
+ (struct
+ (texture (* void)) ; SDL_GPUTexture
+ (mip_level u32)
+ (layer u32)
+ (cycle u8)
+ (_ u8)
+ (_ u8)
+ (_ u8)))
+
+(define-sdl-pointer-type <gpu-device>
+ gpu-device? wrap-gpu-device unwrap-gpu-device
+ gpu-device-destroyed? set-gpu-device-destroyed!
+ (lambda (device port)
+ (display "#<gpu-device>" port)))
+
+(define-sdl-pointer-type <gpu-buffer>
+ gpu-buffer? wrap-gpu-buffer unwrap-gpu-buffer
+ gpu-buffer-released? set-gpu-buffer-released!
+ (lambda (buffer port)
+ (display "#<gpu-buffer>" port)))
+
+(define-sdl-pointer-type <gpu-transfer-buffer>
+ gpu-transfer-buffer? wrap-gpu-transfer-buffer unwrap-gpu-transfer-buffer
+ gpu-transfer-buffer-released? set-gpu-transfer-buffer-released!
+ (lambda (transfer-buffer port)
+ (display "#<gpu-transfer-buffer>" port)))
+
+(define-sdl-pointer-type <gpu-shader>
+ gpu-shader? wrap-gpu-shader unwrap-gpu-shader
+ gpu-shader-released? set-gpu-shader-released!
+ (lambda (shader port)
+ (display "#<gpu-shader>" port)))
+
+(define-sdl-pointer-type <gpu-texture>
+ gpu-texture? wrap-gpu-texture unwrap-gpu-texture
+ gpu-texture-released? set-gpu-texture-released!
+ (lambda (texture port)
+ (format port "#<gpu-texture ~a>"
+ (pointer-address (unwrap-gpu-texture texture)))))
+
+(define-sdl-pointer-type <gpu-graphics-pipeline>
+ gpu-graphics-pipeline? wrap-gpu-graphics-pipeline unwrap-gpu-graphics-pipeline
+ gpu-graphics-pipeline-released? set-gpu-graphics-pipeline-released!
+ (lambda (graphics-pipeline port)
+ (display "#<gpu-graphics-pipeline>" port)))
+
+(define-wrapped-pointer-type <gpu-command-buffer>
+ gpu-command-buffer? wrap-gpu-command-buffer unwrap-gpu-command-buffer
+ (lambda (command-buffer port)
+ (display "#<gpu-command-buffer>" port)))
+
+(define-wrapped-pointer-type <gpu-copy-pass>
+ gpu-copy-pass? wrap-gpu-copy-pass unwrap-gpu-copy-pass
+ (lambda (copy-pass port)
+ (display "#<gpu-copy-pass>" port)))
+
+(define-wrapped-pointer-type <gpu-render-pass>
+ gpu-render-pass? wrap-gpu-render-pass unwrap-gpu-render-pass
+ (lambda (render-pass port)
+ (display "#<gpu-render-pass>" port)))
+
+(define-wrapped-pointer-type <gpu-compute-pass>
+ gpu-compute-pass? wrap-gpu-compute-pass unwrap-gpu-compute-pass
+ (lambda (compute-pass port)
+ (display "#<gpu-compute-pass>" port)))
+
+(define-sdl SDL_AcquireGPUCommandBuffer '* -> '*)
+(define-sdl SDL_AcquireGPUSwapchainTexture '* '* '* '* '* -> bool)
+(define-sdl SDL_BeginGPUCopyPass '* -> '*)
+(define-sdl SDL_BeginGPURenderPass '* '* uint32 '* -> '*)
+(define-sdl SDL_BindGPUGraphicsPipeline '* '*)
+(define-sdl SDL_BindGPUVertexBuffers '* uint32 '* uint32)
+(define-sdl SDL_BlitGPUTexture '* '*)
+(define-sdl SDL_CreateGPUBuffer '* '* -> '*)
+(define-sdl SDL_CreateGPUDevice SDL_GPUShaderFormat bool '* -> '*)
+(define-sdl SDL_CreateGPUGraphicsPipeline '* '* -> '*)
+(define-sdl SDL_CreateGPUShader '* '* -> '*)
+(define-sdl SDL_CreateGPUTexture '* '* -> '*)
+(define-sdl SDL_CreateGPUTransferBuffer '* '* -> '*)
+(define-sdl SDL_ClaimWindowForGPUDevice '* '* -> bool)
+(define-sdl SDL_DestroyGPUDevice '*)
+(define-sdl SDL_DrawGPUPrimitives '* uint32 uint32 uint32 uint32)
+(define-sdl SDL_EndGPUCopyPass '*)
+(define-sdl SDL_EndGPURenderPass '*)
+(define-sdl SDL_GetGPUDeviceDriver '* -> '*)
+(define-sdl SDL_GetGPUDriver int -> '*)
+(define-sdl SDL_GetGPUSwapchainTextureFormat '* '* -> SDL_GPUTextureFormat)
+(define-sdl SDL_GetNumGPUDrivers -> int)
+(define-sdl SDL_GPUTextureSupportsSampleCount '* SDL_GPUTextureFormat SDL_GPUSampleCount -> bool)
+(define-sdl SDL_MapGPUTransferBuffer '* '* bool -> '*)
+(define-sdl SDL_PushGPUFragmentUniformData '* uint32 '* uint32)
+(define-sdl SDL_PushGPUVertexUniformData '* uint32 '* uint32)
+(define-sdl SDL_ReleaseGPUBuffer '* '*)
+(define-sdl SDL_ReleaseGPUGraphicsPipeline '* '*)
+(define-sdl SDL_ReleaseGPUShader '* '*)
+(define-sdl SDL_ReleaseGPUTexture '* '*)
+(define-sdl SDL_ReleaseGPUTransferBuffer '* '*)
+(define-sdl SDL_ReleaseWindowFromGPUDevice '* '*)
+(define-sdl SDL_SetGPUBufferName '* '* '*)
+(define-sdl SDL_SubmitGPUCommandBuffer '* -> bool)
+(define-sdl SDL_UnmapGPUTransferBuffer '* '*)
+(define-sdl SDL_UploadToGPUBuffer '* '* '* bool)
diff --git a/sdl3/bindings/init.scm b/sdl3/bindings/init.scm
new file mode 100644
index 0000000..ac92829
--- /dev/null
+++ b/sdl3/bindings/init.scm
@@ -0,0 +1,49 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_init.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings init)
+ #:use-module (sdl3 bindings utils)
+ #:use-module (system foreign)
+ #:export (SDL_InitFlags
+ SDL_INIT_AUDIO
+ SDL_INIT_VIDEO
+ SDL_INIT_JOYSTICK
+ SDL_INIT_HAPTIC
+ SDL_INIT_GAMEPAD
+ SDL_INIT_EVENTS
+ SDL_INIT_SENSOR
+ SDL_INIT_CAMERA
+
+ SDL_Init
+ SDL_Quit))
+
+(define SDL_InitFlags uint32)
+(define SDL_INIT_AUDIO #x00000010)
+(define SDL_INIT_VIDEO #x00000020)
+(define SDL_INIT_JOYSTICK #x00000200)
+(define SDL_INIT_HAPTIC #x00001000)
+(define SDL_INIT_GAMEPAD #x00002000)
+(define SDL_INIT_EVENTS #x00004000)
+(define SDL_INIT_SENSOR #x00008000)
+(define SDL_INIT_CAMERA #x00010000)
+
+(define-sdl SDL_Init SDL_InitFlags -> bool)
+(define-sdl SDL_Quit)
diff --git a/sdl3/bindings/pixels.scm b/sdl3/bindings/pixels.scm
new file mode 100644
index 0000000..a1f2a28
--- /dev/null
+++ b/sdl3/bindings/pixels.scm
@@ -0,0 +1,41 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_pixels.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings pixels)
+ #:use-module (bstruct)
+ #:use-module (sdl3 bindings utils)
+ #:use-module (system foreign)
+ #:export (SDL_Color
+ SDL_FColor))
+
+(define-bstruct SDL_Color
+ (struct
+ (r u8)
+ (g u8)
+ (b u8)
+ (a u8)))
+
+(define-bstruct SDL_FColor
+ (struct
+ (r f32)
+ (g f32)
+ (b f32)
+ (a f32)))
diff --git a/sdl3/bindings/surface.scm b/sdl3/bindings/surface.scm
new file mode 100644
index 0000000..d9ebd15
--- /dev/null
+++ b/sdl3/bindings/surface.scm
@@ -0,0 +1,36 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_surface.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings surface)
+ #:use-module (sdl3 bindings utils)
+ #:export (SDL_FlipMode
+ symbol->flip-mode
+ flip-mode->symbol
+ SDL_FLIP_NONE
+ SDL_FLIP_HORIZONTAL
+ SDL_FLIP_VERTICAL))
+
+(define-enum SDL_FlipMode
+ symbol->flip-mode
+ flip-mode->symbol
+ (none SDL_FLIP_NONE)
+ (horizontal SDL_FLIP_HORIZONTAL)
+ (vertical SDL_FLIP_VERTICAL))
diff --git a/sdl3/bindings/utils.scm b/sdl3/bindings/utils.scm
new file mode 100644
index 0000000..bdc6942
--- /dev/null
+++ b/sdl3/bindings/utils.scm
@@ -0,0 +1,133 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level FFI binding utilities.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings utils)
+ #:use-module (ice-9 match)
+ #:use-module (sdl3 config)
+ #:use-module (sdl3 guardian)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-9 gnu)
+ #:use-module (system foreign)
+ #:use-module (system foreign-library)
+ #:export (bool
+ define-enum
+ define-bitmask
+ define-sdl
+ define-sdl-pointer-type
+ define-symbol<->enum
+ flags->bitmask))
+
+;; Type aliases:
+(define bool uint8)
+
+(define-syntax enum-case
+ (syntax-rules ()
+ ((_ x) (error "no matching enum" x))
+ ((_ x (var val) . rest)
+ (if (eq? x var) val (enum-case x . rest)))))
+
+(define-syntax define-enum
+ (lambda (stx)
+ (syntax-case stx ()
+ ((_ type-name atom->enum enum->atom (atom name . id) ...)
+ (every identifier? #'(name ...))
+ (with-syntax (((defs ...)
+ (let lp ((i 0) (specs #'((name . id) ...)))
+ (syntax-case specs ()
+ (() '())
+ (((name) . rest)
+ (cons #`(define name #,i)
+ (lp (1+ i) #'rest)))
+ (((name id) . rest)
+ (cons #`(define name id)
+ (lp (1+ (syntax->datum #'id)) #'rest)))))))
+ #'(begin
+ (define type-name int)
+ defs ...
+ (define (atom->enum x)
+ (match x ('atom name) ...))
+ (define (enum->atom x)
+ (enum-case x (name 'atom) ...))))))))
+
+(define-syntax bitmask-case
+ (syntax-rules ()
+ ((_ x) (error "no matching flag" x))
+ ((_ x (var val) . rest)
+ (let ((cont (lambda () (bitmask-case x . rest))))
+ (if (zero? (logand x var))
+ (cont)
+ (cons val (cont)))))))
+
+(define-syntax define-bitmask
+ (lambda (stx)
+ (syntax-case stx ()
+ ((_ (type-name c-type)
+ symbols->bitmask
+ bitmask->symbols
+ (sym name) ...)
+ (every identifier? #'(name ...))
+ (with-syntax (((defs ...)
+ (let lp ((i 1) (names #'(name ...)))
+ (syntax-case names ()
+ (() '())
+ ((name . rest)
+ (cons #`(define name #,i)
+ (lp (ash i 1) #'rest)))))))
+ #'(begin
+ (define type-name c-type)
+ defs ...
+ (define (symbols->bitmask flags)
+ (fold (lambda (flag result)
+ (logior (match flag ('sym name) ...)
+ result))
+ 0 flags))
+ (define (bitmask->symbols x)
+ (bitmask-case x (name 'sym) ...))))))))
+
+
+(define-syntax define-sdl
+ (lambda (stx)
+ (syntax-case stx (->)
+ ((_ name arg-type ... -> return-type)
+ #`(define name
+ (foreign-library-function %libsdl3
+ #,(symbol->string (syntax->datum #'name))
+ #:arg-types (list arg-type ...)
+ #:return-type return-type)))
+ ((_ name arg-type ...)
+ #'(define-sdl name arg-type ... -> void)))))
+
+(define-syntax-rule (define-sdl-pointer-type name
+ pred wrap unwrap
+ destroyed-pred set-destroyed
+ print
+ (field accessors ...) ...)
+ (begin
+ (define-record-type name
+ (ctor ptr)
+ pred
+ (ptr unwrap)
+ (destroyed? destroyed-pred set-destroyed)
+ (field accessors ...) ...)
+ (define (wrap ptr)
+ (sdl-protect (ctor ptr)))
+ (set-record-type-printer! name print)))
diff --git a/sdl3/bindings/video.scm b/sdl3/bindings/video.scm
new file mode 100644
index 0000000..40ee4cc
--- /dev/null
+++ b/sdl3/bindings/video.scm
@@ -0,0 +1,103 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level bindings for SDL_video.h.
+;;
+;;; Code:
+
+(define-module (sdl3 bindings video)
+ #:use-module (sdl3 bindings utils)
+ #:use-module (system foreign)
+ #:export (SDL_DisplayID
+ SDL_WindowID
+
+ SDL_WindowFlags
+ SDL_WINDOW_FULLSCREEN
+ SDL_WINDOW_OPENGL
+ SDL_WINDOW_OCCLUDED
+ SDL_WINDOW_HIDDEN
+ SDL_WINDOW_BORDERLESS
+ SDL_WINDOW_RESIZABLE
+ SDL_WINDOW_MINIMIZED
+ SDL_WINDOW_MAXIMIZED
+ SDL_WINDOW_MOUSE_GRABBED
+ SDL_WINDOW_INPUT_FOCUS
+ SDL_WINDOW_MOUSE_FOCUS
+ SDL_WINDOW_EXTERNAL
+ SDL_WINDOW_MODAL
+ SDL_WINDOW_HIGH_PIXEL_DENSITY
+ SDL_WINDOW_MOUSE_CAPTURE
+ SDL_WINDOW_MOUSE_RELATIVE_MODE
+ SDL_WINDOW_ALWAYS_ON_TOP
+ SDL_WINDOW_UTILITY
+ SDL_WINDOW_TOOLTIP
+ SDL_WINDOW_POPUP_MENU
+ SDL_WINDOW_KEYBOARD_GRABBED
+ SDL_WINDOW_VULKAN
+ SDL_WINDOW_METAL
+ SDL_WINDOW_TRANSPARENT
+ SDL_WINDOW_NOT_FOCUSABLE
+
+ window?
+ wrap-window
+ unwrap-window
+ window-destroyed?
+ set-window-destroyed!
+
+ SDL_CreateWindow
+ SDL_DestroyWindow
+ SDL_GetWindowSizeInPixels))
+
+(define SDL_DisplayID uint32)
+(define SDL_WindowID uint32)
+
+(define SDL_WindowFlags uint64)
+(define SDL_WINDOW_FULLSCREEN #x0000000000000001)
+(define SDL_WINDOW_OPENGL #x0000000000000002)
+(define SDL_WINDOW_OCCLUDED #x0000000000000004)
+(define SDL_WINDOW_HIDDEN #x0000000000000008)
+(define SDL_WINDOW_BORDERLESS #x0000000000000010)
+(define SDL_WINDOW_RESIZABLE #x0000000000000020)
+(define SDL_WINDOW_MINIMIZED #x0000000000000040)
+(define SDL_WINDOW_MAXIMIZED #x0000000000000080)
+(define SDL_WINDOW_MOUSE_GRABBED #x0000000000000100)
+(define SDL_WINDOW_INPUT_FOCUS #x0000000000000200)
+(define SDL_WINDOW_MOUSE_FOCUS #x0000000000000400)
+(define SDL_WINDOW_EXTERNAL #x0000000000000800)
+(define SDL_WINDOW_MODAL #x0000000000001000)
+(define SDL_WINDOW_HIGH_PIXEL_DENSITY #x0000000000002000)
+(define SDL_WINDOW_MOUSE_CAPTURE #x0000000000004000)
+(define SDL_WINDOW_MOUSE_RELATIVE_MODE #x0000000000008000)
+(define SDL_WINDOW_ALWAYS_ON_TOP #x0000000000010000)
+(define SDL_WINDOW_UTILITY #x0000000000020000)
+(define SDL_WINDOW_TOOLTIP #x0000000000040000)
+(define SDL_WINDOW_POPUP_MENU #x0000000000080000)
+(define SDL_WINDOW_KEYBOARD_GRABBED #x0000000000100000)
+(define SDL_WINDOW_VULKAN #x0000000010000000)
+(define SDL_WINDOW_METAL #x0000000020000000)
+(define SDL_WINDOW_TRANSPARENT #x0000000040000000)
+(define SDL_WINDOW_NOT_FOCUSABLE #x0000000080000000)
+
+(define-sdl-pointer-type <window>
+ window? wrap-window unwrap-window
+ window-destroyed? set-window-destroyed!
+ (lambda (window port)
+ (display "#<window>" port)))
+
+(define-sdl SDL_CreateWindow '* int int SDL_WindowFlags -> '*)
+(define-sdl SDL_DestroyWindow '*)
+(define-sdl SDL_GetWindowSizeInPixels '* '* '* -> bool)
diff --git a/sdl3/config.scm.in b/sdl3/config.scm.in
new file mode 100644
index 0000000..5d3c614
--- /dev/null
+++ b/sdl3/config.scm.in
@@ -0,0 +1,26 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+(define-module (sdl3 config)
+ #:export (%libsdl3))
+
+(define-syntax define-canonical
+ (lambda (stx)
+ (syntax-case stx ()
+ ((_ name file)
+ (with-syntax ((file (canonicalize-path (syntax->datum #'file))))
+ #'(define name file))))))
+
+(define-canonical %libsdl3 "@SDL3_LIBDIR@/libSDL3.so")
diff --git a/sdl3/errors.scm b/sdl3/errors.scm
new file mode 100644
index 0000000..3d48647
--- /dev/null
+++ b/sdl3/errors.scm
@@ -0,0 +1,54 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; SDL3 errors.
+;;
+;;; Code:
+
+(define-module (sdl3 errors)
+ #:use-module (ice-9 exceptions)
+ #:use-module (sdl3 bindings error)
+ #:use-module (system foreign)
+ #:export (sdl-get-error
+ make-sdl-error
+ sdl-assert
+ sdl-assert-non-null))
+
+(define (sdl-get-error)
+ (pointer->string (SDL_GetError)))
+
+(define-exception-type &sdl-exception &error
+ make-sdl-exception
+ sdl-exception?)
+
+(define* (make-sdl-error origin #:key
+ (message (sdl-get-error))
+ (irritants '()))
+ (make-exception
+ (make-sdl-exception)
+ (make-exception-with-message message)
+ (make-exception-with-irritants irritants)
+ (make-exception-with-origin origin)))
+
+(define (sdl-assert origin bool)
+ (unless (eq? bool 1)
+ (raise-exception (make-sdl-error origin))))
+
+(define (sdl-assert-non-null origin pointer)
+ (when (null-pointer? pointer)
+ (raise-exception (make-sdl-error origin)))
+ pointer)
diff --git a/sdl3/events.scm b/sdl3/events.scm
new file mode 100644
index 0000000..be0e0ef
--- /dev/null
+++ b/sdl3/events.scm
@@ -0,0 +1,43 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; Low-level FFI binding utilities.
+;;
+;;; Code:
+
+(define-module (sdl3 events)
+ #:use-module (bstruct)
+ #:use-module (sdl3 bindings events)
+ #:use-module (system foreign)
+ #:export (event?
+ event-type
+ poll-event))
+
+(define (make-event)
+ (bstruct-alloc SDL_Event))
+
+(define (event? obj)
+ (bstruct? SDL_Event obj))
+
+(define (event-type event)
+ (event-type->symbol (bstruct-ref SDL_Event event type)))
+
+(define (poll-event)
+ (and (eq? (SDL_PollEvent %null-pointer) 1)
+ (let ((event (make-event)))
+ (SDL_PollEvent (bstruct->pointer SDL_Event event))
+ event)))
diff --git a/sdl3/gpu.scm b/sdl3/gpu.scm
new file mode 100644
index 0000000..e46a38c
--- /dev/null
+++ b/sdl3/gpu.scm
@@ -0,0 +1,966 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; SDL3 3D rendering and GPU compute.
+;;
+;;; Code:
+
+(define-module (sdl3 gpu)
+ #:use-module (bstruct)
+ #:use-module (ice-9 match)
+ #:use-module (rnrs bytevectors)
+ #:use-module (sdl3 bindings gpu)
+ #:use-module (sdl3 bindings surface)
+ #:use-module (sdl3 bindings video)
+ #:use-module (sdl3 errors)
+ #:use-module (srfi srfi-9)
+ #:use-module (system foreign)
+ #:export (num-gpu-drivers
+ gpu-driver
+
+ make-gpu-device
+ destroy-gpu-device!
+ gpu-device-driver
+ claim-window-for-gpu-device!
+ release-window-from-gpu-device!
+ gpu-texture-supports-sample-count?
+ gpu-swapchain-texture-format
+
+ make-gpu-buffer
+ release-gpu-buffer!
+ set-gpu-buffer-name!
+
+ make-gpu-transfer-buffer
+ release-gpu-transfer-buffer!
+ map-gpu-transfer-buffer!
+ unmap-gpu-transfer-buffer!
+
+ make-gpu-shader
+ release-gpu-shader!
+
+ make-gpu-texture
+ release-gpu-texture!
+
+ make-gpu-vertex-buffer-description
+ gpu-vertex-buffer-description?
+ gpu-vertex-buffer-description-slot
+ gpu-vertex-buffer-description-pitch
+ gpu-vertex-buffer-description-input-rate
+ gpu-vertex-buffer-description-instance-step-rate
+
+ make-gpu-vertex-attribute
+ gpu-vertex-attribute?
+ gpu-vertex-attribute-location
+ gpu-vertex-attribute-buffer-slot
+ gpu-vertex-attribute-format
+ gpu-vertex-attribute-offset
+
+ make-gpu-vertex-input-state
+ gpu-vertex-input-state?
+ gpu-vertex-input-state-vertex-buffer-descriptions
+ gpu-vertex-input-state-vertex-attributes
+
+ make-gpu-stencil-op-state
+ gpu-stencil-op-state?
+ gpu-stencil-op-state-fail
+ gpu-stencil-op-state-pass
+ gpu-stencil-op-state-depth-fail
+ gpu-stencil-op-state-compare
+
+ make-gpu-color-target-blend-state
+ gpu-color-target-blend-state?
+ gpu-color-target-blend-state-src-color-factor
+ gpu-color-target-blend-state-dst-color-factor
+ gpu-color-target-blend-state-color-op
+ gpu-color-target-blend-state-src-alpha-factor
+ gpu-color-target-blend-state-dst-alpha-factor
+ gpu-color-target-blend-state-alpha-op
+ gpu-color-target-blend-state-color-write-mask
+
+ make-gpu-rasterizer-state
+ gpu-rasterizer-state?
+ gpu-rasterizer-state-fill-mode
+ gpu-rasterizer-state-cull-mode
+ gpu-rasterizer-state-front-face
+ gpu-rasterizer-state-depth-bias-constant-factor
+ gpu-rasterizer-state-depth-bias-clamp
+ gpu-rasterizer-state-depth-bias-slope-factor
+ gpu-rasterizer-state-depth-clip?
+
+ make-gpu-multisample-state
+ gpu-multisample-state?
+ gpu-multisample-state-sample-count
+ gpu-multisample-state-sample-mask
+
+ make-gpu-depth-stencil-state
+ gpu-depth-stencil-state?
+ gpu-depth-stencil-state-compare-op
+ gpu-depth-stencil-state-back-stencil-state
+ gpu-depth-stencil-state-front-stencil-state
+ gpu-depth-stencil-state-compare-mask
+ gpu-depth-stencil-state-write-mask
+
+ make-gpu-color-target-description
+ gpu-color-target-description?
+ gpu-color-target-description-format
+ gpu-color-target-description-blend-state
+
+ make-gpu-graphics-pipeline-target-info
+ gpu-graphics-pipeline-target-info?
+ gpu-graphics-pipeline-target-info-color-targets
+ gpu-graphics-pipeline-target-info-depth-stencil-format
+
+ make-gpu-graphics-pipeline
+ release-gpu-graphics-pipeline!
+
+ acquire-gpu-command-buffer
+ submit-gpu-command-buffer!
+ acquire-gpu-swapchain-texture
+ push-gpu-fragment-uniform-data
+ push-gpu-vertex-uniform-data
+ make-gpu-blit-info
+ gpu-blit-info?
+ set-gpu-blit-info-source-texture!
+ set-gpu-blit-info-destination-texture!
+ blit-gpu-texture
+
+ begin-gpu-copy-pass
+ end-gpu-copy-pass
+ upload-to-gpu-buffer
+
+ make-gpu-color-target
+ set-gpu-color-target-texture!
+
+ make-gpu-depth-stencil-target
+ make-gpu-buffer-binding
+
+ begin-gpu-render-pass
+ end-gpu-render-pass
+ bind-gpu-graphics-pipeline
+ bind-gpu-vertex-buffers
+ draw-gpu-primitives)
+ #:re-export (gpu-device?
+ gpu-device-destroyed?
+
+ gpu-buffer?
+ gpu-buffer-released?
+
+ gpu-transfer-buffer?
+ gpu-transfer-buffer-released?
+
+ gpu-shader?
+ gpu-shader-released?
+
+ gpu-texture?
+ gpu-texture-released?
+
+ gpu-graphics-pipeline?
+ gpu-graphics-pipeline-released?
+
+ gpu-command-buffer?
+ gpu-copy-pass?
+ gpu-render-pass?
+ gpu-compute-pass?))
+
+(define-syntax-rule (define-record-type* name
+ (constructor arg-spec ...)
+ pred
+ (field accessors ...)
+ ...)
+ (begin
+ (define-record-type name
+ (%constructor field ...)
+ pred
+ (field accessors ...) ...)
+ (define* (constructor arg-spec ...)
+ (%constructor field ...))))
+
+(define-syntax-rule (bstruct-alloc-pointer type elems ...)
+ (bstruct->pointer type (bstruct-alloc type elems ...)))
+
+(define (gpu-num-gpu-drivers)
+ (SDL_GetNumGPUDrivers))
+
+(define (gpu-driver index)
+ (pointer->string
+ (sdl-assert-non-null
+ 'gpu-driver
+ (SDL_GetGPUDriver index))))
+
+
+;;;
+;;; Devices
+;;;
+
+(define* (make-gpu-device shader-formats #:key debug? driver)
+ (wrap-gpu-device
+ (sdl-assert-non-null
+ 'make-gpu-device
+ (SDL_CreateGPUDevice (symbols->gpu-shader-format shader-formats)
+ (if debug? 1 0)
+ (if driver
+ (string->pointer driver)
+ %null-pointer)))))
+
+(define (destroy-gpu-device! device)
+ (unless (gpu-device-destroyed? device)
+ (SDL_DestroyGPUDevice (unwrap-gpu-device device))
+ (set-gpu-device-destroyed! device #t)))
+
+(define (gpu-device-driver device)
+ (pointer->string
+ (sdl-assert-non-null
+ 'gpu-device-driver
+ (SDL_GetGPUDeviceDriver (unwrap-gpu-device device)))))
+
+(define (claim-window-for-gpu-device! device window)
+ (sdl-assert
+ 'claim-window-for-gpu-device!
+ (SDL_ClaimWindowForGPUDevice (unwrap-gpu-device device)
+ (unwrap-window window))))
+
+(define (release-window-from-gpu-device! device window)
+ (SDL_ReleaseWindowFromGPUDevice (unwrap-gpu-device device)
+ (unwrap-window window)))
+
+(define (gpu-texture-supports-sample-count? device format sample-count)
+ (eq? (SDL_GPUTextureSupportsSampleCount (unwrap-gpu-device device)
+ (symbol->gpu-texture-format format)
+ (int->gpu-sample-count sample-count))
+ 1))
+
+(define (gpu-swapchain-texture-format device window)
+ (gpu-texture-format->symbol
+ (SDL_GetGPUSwapchainTextureFormat (unwrap-gpu-device device)
+ (unwrap-window window))))
+
+
+;;;
+;;; Buffers
+;;;
+
+(define (make-gpu-buffer device size usage)
+ (wrap-gpu-buffer
+ (sdl-assert-non-null
+ 'make-gpu-buffer
+ (SDL_CreateGPUBuffer (unwrap-gpu-device device)
+ (bstruct-alloc-pointer
+ SDL_GPUBufferCreateInfo
+ (usage (symbols->gpu-buffer-usage-flags usage))
+ (size size))))))
+
+(define (release-gpu-buffer! device buffer)
+ (unless (gpu-buffer-released? buffer)
+ (SDL_ReleaseGPUBuffer (unwrap-gpu-device device)
+ (unwrap-gpu-buffer buffer))
+ (set-gpu-buffer-released! buffer #t)))
+
+(define (set-gpu-buffer-name! device buffer name)
+ (SDL_SetGPUBufferName (unwrap-gpu-device device)
+ (unwrap-gpu-buffer buffer)
+ (string->pointer name)))
+
+
+;;;
+;;; Transfer buffers
+;;;
+
+(define (make-gpu-transfer-buffer device size usage)
+ (wrap-gpu-transfer-buffer
+ (sdl-assert-non-null
+ 'make-gpu-transfer-buffer
+ (SDL_CreateGPUTransferBuffer (unwrap-gpu-device device)
+ (bstruct-alloc-pointer
+ SDL_GPUTransferBufferCreateInfo
+ (usage (symbol->gpu-transfer-buffer-usage usage))
+ (size size))))))
+
+(define (release-gpu-transfer-buffer! device buffer)
+ (unless (gpu-transfer-buffer-released? buffer)
+ (SDL_ReleaseGPUTransferBuffer (unwrap-gpu-device device)
+ (unwrap-gpu-transfer-buffer buffer))
+ (set-gpu-transfer-buffer-released! buffer #t)))
+
+(define* (map-gpu-transfer-buffer! device buffer len #:optional cycle?)
+ (pointer->bytevector
+ (sdl-assert-non-null
+ 'map-gpu-transfer-buffer!
+ (SDL_MapGPUTransferBuffer (unwrap-gpu-device device)
+ (unwrap-gpu-transfer-buffer buffer)
+ (if cycle? 1 0)))
+ len))
+
+(define (unmap-gpu-transfer-buffer! device buffer)
+ (SDL_UnmapGPUTransferBuffer (unwrap-gpu-device device)
+ (unwrap-gpu-transfer-buffer buffer)))
+
+
+;;;
+;;; Shaders
+;;;
+
+(define* (make-gpu-shader device stage format code #:key
+ (samplers 0)
+ (storage-buffers 0)
+ (uniform-buffers 0)
+ (entry-point "main"))
+ (wrap-gpu-shader
+ (sdl-assert-non-null
+ 'make-gpu-shader
+ (SDL_CreateGPUShader (unwrap-gpu-device device)
+ (bstruct-alloc-pointer
+ SDL_GPUShaderCreateInfo
+ (code_size (bytevector-length code))
+ (code (bytevector->pointer code))
+ (entrypoint (string->pointer entry-point))
+ (format (symbols->gpu-shader-format (list format)))
+ (stage (symbol->gpu-shader-stage stage))
+ (num_samplers samplers)
+ (num_storage_buffers storage-buffers)
+ (num_uniform_buffers uniform-buffers))))))
+
+(define (release-gpu-shader! device shader)
+ (unless (gpu-shader-released? shader)
+ (SDL_ReleaseGPUShader (unwrap-gpu-device device)
+ (unwrap-gpu-shader shader))
+ (set-gpu-shader-released! shader #t)))
+
+
+;;;
+;;; Textures
+;;;
+
+(define* (make-gpu-texture device
+ #:key
+ (type '2d)
+ (format 'r8g8b8a8-unorm)
+ (usage '(color-target))
+ (width 1)
+ (height 1)
+ (layer-count-or-depth 1)
+ (levels 1)
+ (sample-count 1))
+ (wrap-gpu-texture
+ (sdl-assert-non-null
+ 'make-gpu-texture
+ (SDL_CreateGPUTexture (unwrap-gpu-device device)
+ (bstruct-alloc-pointer
+ SDL_GPUTextureCreateInfo
+ (type (symbol->gpu-texture-type type))
+ (format (symbol->gpu-texture-format format))
+ (usage (symbols->gpu-texture-usage-flags usage))
+ (width width)
+ (height height)
+ (layer_count_or_depth layer-count-or-depth)
+ (num_levels levels)
+ (sample_count (int->gpu-sample-count sample-count)))))))
+
+(define (release-gpu-texture! device texture)
+ (unless (gpu-texture-released? texture)
+ (SDL_ReleaseGPUTexture (unwrap-gpu-device device)
+ (unwrap-gpu-texture texture))
+ (set-gpu-texture-released! texture #t)))
+
+
+;;;
+;;; Graphics pipelines
+;;;
+
+(define-record-type* <gpu-vertex-buffer-description>
+ (make-gpu-vertex-buffer-description #:key slot pitch (input-rate 'vertex) (instance-step-rate 0))
+ gpu-vertex-buffer-description?
+ (slot gpu-vertex-buffer-description-slot)
+ (pitch gpu-vertex-buffer-description-pitch)
+ (input-rate gpu-vertex-buffer-description-input-rate)
+ (instance-step-rate gpu-vertex-buffer-description-instance-step-rate))
+
+(define-record-type* <gpu-vertex-attribute>
+ (make-gpu-vertex-attribute #:key location buffer-slot format (offset 0))
+ gpu-vertex-attribute?
+ (location gpu-vertex-attribute-location)
+ (buffer-slot gpu-vertex-attribute-buffer-slot)
+ (format gpu-vertex-attribute-format)
+ (offset gpu-vertex-attribute-offset))
+
+(define-record-type* <gpu-vertex-input-state>
+ (make-gpu-vertex-input-state #:key
+ (vertex-buffer-descriptions #())
+ (vertex-attributes #()))
+ gpu-vertex-input-state?
+ (vertex-buffer-descriptions gpu-vertex-input-state-vertex-buffer-descriptions)
+ (vertex-attributes gpu-vertex-input-state-vertex-attributes))
+
+(define-record-type* <gpu-stencil-op-state>
+ (make-gpu-stencil-op-state #:key
+ (fail 'keep)
+ (pass 'keep)
+ (depth-fail 'keep)
+ (compare 'always))
+ gpu-stencil-op-state?
+ (fail gpu-stencil-op-state-fail)
+ (pass gpu-stencil-op-state-pass)
+ (depth-fail gpu-stencil-op-state-depth-fail)
+ (compare gpu-stencil-op-state-compare))
+
+(define-record-type* <gpu-color-target-blend-state>
+ (make-gpu-color-target-blend-state #:key
+ (src-color-factor 'one)
+ (dst-color-factor 'zero)
+ (color-op 'add)
+ (src-alpha-factor 'one)
+ (dst-alpha-factor 'zero)
+ (alpha-op 'add)
+ (color-write-mask '(r g b a)))
+ gpu-color-target-blend-state?
+ (src-color-factor gpu-color-target-blend-state-src-color-factor)
+ (dst-color-factor gpu-color-target-blend-state-dst-color-factor)
+ (color-op gpu-color-target-blend-state-color-op)
+ (src-alpha-factor gpu-color-target-blend-state-src-alpha-factor)
+ (dst-alpha-factor gpu-color-target-blend-state-dst-alpha-factor)
+ (alpha-op gpu-color-target-blend-state-alpha-op)
+ (color-write-mask gpu-color-target-blend-state-color-write-mask))
+
+(define-record-type* <gpu-rasterizer-state>
+ (make-gpu-rasterizer-state #:key
+ (fill-mode 'fill)
+ (cull-mode 'none)
+ (front-face 'counter-clockwise)
+ depth-bias-constant-factor
+ depth-bias-clamp
+ depth-bias-slope-factor
+ depth-clip?)
+ gpu-rasterizer-state?
+ (fill-mode gpu-rasterizer-state-fill-mode)
+ (cull-mode gpu-rasterizer-state-cull-mode)
+ (front-face gpu-rasterizer-state-front-face)
+ (depth-bias-constant-factor gpu-rasterizer-state-depth-bias-constant-factor)
+ (depth-bias-clamp gpu-rasterizer-state-depth-bias-clamp)
+ (depth-bias-slope-factor gpu-rasterizer-state-depth-bias-slope-factor)
+ (depth-clip? gpu-rasterizer-state-depth-clip?))
+
+(define-record-type* <gpu-multisample-state>
+ (make-gpu-multisample-state #:key
+ (sample-count 1)
+ (sample-mask #xffffffff))
+ gpu-multisample-state?
+ (sample-count gpu-multisample-state-sample-count)
+ (sample-mask gpu-multisample-state-sample-mask))
+
+(define-record-type* <gpu-depth-stencil-state>
+ (make-gpu-depth-stencil-state #:key
+ (compare-op 'always)
+ (back-stencil-state (make-gpu-stencil-op-state))
+ (front-stencil-state (make-gpu-stencil-op-state))
+ (compare-mask #xff)
+ (write-mask #xff))
+ gpu-depth-stencil-state?
+ (compare-op gpu-depth-stencil-state-compare-op)
+ (back-stencil-state gpu-depth-stencil-state-back-stencil-state)
+ (front-stencil-state gpu-depth-stencil-state-front-stencil-state)
+ (compare-mask gpu-depth-stencil-state-compare-mask)
+ (write-mask gpu-depth-stencil-state-write-mask))
+
+(define-record-type* <gpu-color-target-description>
+ (make-gpu-color-target-description #:key
+ format
+ (blend-state #f))
+ gpu-color-target-description?
+ (format gpu-color-target-description-format)
+ (blend-state gpu-color-target-description-blend-state))
+
+(define-record-type* <gpu-graphics-pipeline-target-info>
+ (make-gpu-graphics-pipeline-target-info #:key
+ (color-targets #())
+ depth-stencil-format)
+ gpu-graphics-pipeline-target-info?
+ (color-targets gpu-graphics-pipeline-target-info-color-targets)
+ (depth-stencil-format gpu-graphics-pipeline-target-info-depth-stencil-format))
+
+(define* (make-gpu-graphics-pipeline device #:key
+ vertex-shader
+ fragment-shader
+ vertex-input-state
+ (primitive-type 'triangle-list)
+ (rasterizer-state (make-gpu-rasterizer-state))
+ multisample-state
+ depth-stencil-state
+ target-info)
+ (match-let ((($ <gpu-vertex-input-state> vertex-buffer-descriptions
+ vertex-attributes)
+ vertex-input-state)
+ (($ <gpu-rasterizer-state> fill-mode
+ cull-mode
+ front-face
+ depth-bias-constant-factor
+ depth-bias-clamp
+ depth-bias-slope-factor
+ depth-clip?)
+ rasterizer-state)
+ (($ <gpu-multisample-state> sample-count sample-mask)
+ multisample-state)
+ (($ <gpu-depth-stencil-state> compare-op
+ ($ <gpu-stencil-op-state> back-fail
+ back-pass
+ back-depth-fail
+ back-compare)
+ ($ <gpu-stencil-op-state> front-fail
+ front-pass
+ front-depth-fail
+ front-compare)
+ compare-mask
+ write-mask)
+ depth-stencil-state)
+ (($ <gpu-graphics-pipeline-target-info> color-targets
+ depth-stencil-format)
+ target-info))
+ ;; Build vertex buffer description structs.
+ ;; TODO: bstructs should provide a macro to make this easier.
+ (define num-vert-descs (vector-length vertex-buffer-descriptions))
+ (define vert-descs
+ (make-bytevector (* (bstruct-sizeof SDL_GPUVertexBufferDescription)
+ num-vert-descs)))
+ (do ((i 0 (1+ i)))
+ ((= i num-vert-descs))
+ (match (vector-ref vertex-buffer-descriptions i)
+ (($ <gpu-vertex-buffer-description> slot pitch input-rate
+ instance-step-rate)
+ (bstruct-pack!
+ SDL_GPUVertexBufferDescription
+ vert-descs
+ (* (bstruct-sizeof SDL_GPUVertexBufferDescription) i)
+ (slot slot)
+ (pitch pitch)
+ (input_rate (symbol->gpu-vertex-input-rate input-rate))
+ (instance_step_rate instance-step-rate)))))
+ ;; Build vertex attrifbute structsl
+ (define num-vert-attrs (vector-length vertex-attributes))
+ (define vert-attrs
+ (make-bytevector (* (bstruct-sizeof SDL_GPUVertexAttribute)
+ num-vert-attrs)))
+ (do ((i 0 (1+ i)))
+ ((= i num-vert-attrs))
+ (match (vector-ref vertex-attributes i)
+ (($ <gpu-vertex-attribute> location buffer-slot format offset)
+ (bstruct-pack!
+ SDL_GPUVertexAttribute
+ vert-attrs
+ (* (bstruct-sizeof SDL_GPUVertexAttribute) i)
+ (location location)
+ (buffer_slot buffer-slot)
+ (format (symbol->gpu-vertex-element-format format))
+ (offset offset)))))
+ ;; Build color target structs.
+ (define num-color-targets (vector-length color-targets))
+ (define color-target-descs
+ (make-bytevector (* (bstruct-sizeof SDL_GPUColorTargetDescription)
+ num-color-targets)))
+ (do ((i 0 (1+ i)))
+ ((= i num-color-targets))
+ (match (vector-ref color-targets i)
+ (($ <gpu-color-target-description> format #f)
+ (bstruct-pack!
+ SDL_GPUColorTargetDescription
+ color-target-descs
+ (* (bstruct-sizeof SDL_GPUColorTargetDescription) i)
+ (format (symbol->gpu-texture-format format))))
+ (($ <gpu-color-target-description>
+ format
+ ($ <gpu-color-target-blend-state>
+ src-color-factor
+ dst-color-factor
+ color-op
+ src-alpha-factor
+ dst-alpha-factor
+ alpha-op
+ color-write-mask))
+ (bstruct-pack!
+ SDL_GPUColorTargetDescription
+ color-target-descs
+ (* (bstruct-sizeof SDL_GPUColorTargetDescription) i)
+ (format (symbol->gpu-texture-format format))
+ ((blend_state src_color_blendfactor)
+ (symbol->gpu-blend-factor src-color-factor))
+ ((blend_state dst_color_blendfactor)
+ (symbol->gpu-blend-factor dst-color-factor))
+ ((blend_state color_blend_op)
+ (symbol->gpu-blend-op color-op))
+ ((blend_state src_alpha_blendfactor)
+ (symbol->gpu-blend-factor src-alpha-factor))
+ ((blend_state dst_alpha_blendfactor)
+ (symbol->gpu-blend-factor dst-alpha-factor))
+ ((blend_state alpha_blend_op)
+ (symbol->gpu-blend-op alpha-op))
+ ((blend_state color_write_mask)
+ (symbols->gpu-color-component-flags color-write-mask))
+ ((blend_state enable_blend) 1)
+ ((blend_state enable_color_write_mask) 1)))))
+ ;; Build giant pipeline descriptor struct.
+ ;; TODO: bstructs should provide syntax for nested struct initialization
+ (define desc
+ (bstruct-alloc
+ SDL_GPUGraphicsPipelineCreateInfo
+ (vertex_shader (unwrap-gpu-shader vertex-shader))
+ (fragment_shader (unwrap-gpu-shader fragment-shader))
+ ((vertex_input_state vertex_buffer_descriptions) (bytevector->pointer vert-descs))
+ ((vertex_input_state num_vertex_buffers) num-vert-descs)
+ ((vertex_input_state vertex_attributes) (bytevector->pointer vert-attrs))
+ ((vertex_input_state num_vertex_attributes) num-vert-attrs)
+ (primitive_type (symbol->gpu-primitive-type primitive-type))
+ ((rasterizer_state fill_mode) (symbol->gpu-fill-mode fill-mode))
+ ((rasterizer_state cull_mode) (symbol->gpu-cull-mode cull-mode))
+ ((rasterizer_state front_face) (symbol->gpu-front-face front-face))
+ ((rasterizer_state enable_depth_clip) (if depth-clip? 1 0))
+ ((rasterizer_state enable_depth_bias)
+ (if (and depth-bias-constant-factor
+ depth-bias-clamp
+ depth-bias-slope-factor)
+ 1 0))
+ ((rasterizer_state depth_bias_constant_factor)
+ (or depth-bias-constant-factor 0.0))
+ ((rasterizer_state depth_bias_clamp)
+ (or depth-bias-clamp 0.0))
+ ((rasterizer_state depth_bias_slope_factor)
+ (or depth-bias-slope-factor 0.0))
+ ((multisample_state sample_count) (int->gpu-sample-count sample-count))
+ ((multisample_state sample_mask) sample-mask)
+ ((multisample_state enable_mask) 1)
+ ((depth_stencil_state compare_op) (symbol->gpu-compare-op compare-op))
+ ((depth_stencil_state back_stencil_state fail_op)
+ (symbol->gpu-stencil-op back-fail))
+ ((depth_stencil_state back_stencil_state pass_op)
+ (symbol->gpu-stencil-op back-pass))
+ ((depth_stencil_state back_stencil_state depth_fail_op)
+ (symbol->gpu-stencil-op back-depth-fail))
+ ((depth_stencil_state back_stencil_state compare_op)
+ (symbol->gpu-compare-op back-compare))
+ ((depth_stencil_state front_stencil_state fail_op)
+ (symbol->gpu-stencil-op front-fail))
+ ((depth_stencil_state front_stencil_state pass_op)
+ (symbol->gpu-stencil-op front-pass))
+ ((depth_stencil_state front_stencil_state depth_fail_op)
+ (symbol->gpu-stencil-op front-depth-fail))
+ ((depth_stencil_state front_stencil_state compare_op)
+ (symbol->gpu-compare-op front-compare))
+ ((depth_stencil_state compare_mask) compare-mask)
+ ((depth_stencil_state write_mask) compare-mask)
+ ((depth_stencil_state enable_depth_test) 1)
+ ((depth_stencil_state enable_depth_write) 1)
+ ((depth_stencil_state enable_stencil_test) 0)
+ ((target_info color_target_descriptions)
+ (bytevector->pointer color-target-descs))
+ ((target_info num_color_targets) num-color-targets)
+ ((target_info depth_stencil_format)
+ (symbol->gpu-texture-format depth-stencil-format))
+ ((target_info has_depth_stencil_target) 1)))
+ (wrap-gpu-graphics-pipeline
+ (sdl-assert-non-null
+ 'make-gpu-graphics-pipeline
+ (SDL_CreateGPUGraphicsPipeline (unwrap-gpu-device device)
+ (bstruct->pointer
+ SDL_GPUGraphicsPipelineCreateInfo
+ desc))))))
+
+(define (release-gpu-graphics-pipeline! device graphics-pipeline)
+ (unless (gpu-graphics-pipeline-released? graphics-pipeline)
+ (SDL_ReleaseGPUGraphicsPipeline (unwrap-gpu-device device)
+ (unwrap-gpu-graphics-pipeline
+ graphics-pipeline))
+ (set-gpu-graphics-pipeline-released! graphics-pipeline #t)))
+
+
+;;;
+;;; Command buffers
+;;;
+
+;; TODO: Do the same pointers get used over and over for buffers and
+;; passes? If so we should cache them to avoid allocation of FFI
+;; pointer objects.
+(define (acquire-gpu-command-buffer device)
+ (wrap-gpu-command-buffer
+ (sdl-assert-non-null
+ 'acquire-gpu-command-buffer
+ (SDL_AcquireGPUCommandBuffer (unwrap-gpu-device device)))))
+
+(define (submit-gpu-command-buffer! cmd)
+ (sdl-assert
+ 'submit-gpu-command-buffer
+ (SDL_SubmitGPUCommandBuffer (unwrap-gpu-command-buffer cmd))))
+
+(define-bstruct <swapchain-info>
+ (struct
+ (texture (* void))
+ (width u32)
+ (height u32)))
+
+;; TODO: This gets called every frame so we need to get rid of the
+;; allocation. The swapchain texture is cycled so the same pointers
+;; get reused over and over.
+(define (acquire-gpu-swapchain-texture cmd window)
+ (let ((info (bstruct-alloc <swapchain-info>)))
+ (sdl-assert
+ 'acquire-gpu-swapchain-texture
+ (SDL_AcquireGPUSwapchainTexture (unwrap-gpu-command-buffer cmd)
+ (unwrap-window window)
+ (bstruct->pointer <swapchain-info>
+ info texture)
+ (bstruct->pointer <swapchain-info>
+ info width)
+ (bstruct->pointer <swapchain-info>
+ info height)))
+ (values (wrap-gpu-texture (bstruct-ref <swapchain-info> info texture))
+ (bstruct-ref <swapchain-info> info width)
+ (bstruct-ref <swapchain-info> info height))))
+
+(define* (push-gpu-fragment-uniform-data cmd slot data #:optional
+ (length (bytevector-length data))
+ (offset 0))
+ (SDL_PushGPUFragmentUniformData (unwrap-gpu-command-buffer cmd)
+ slot
+ (bytevector->pointer data offset)
+ length))
+
+(define* (push-gpu-vertex-uniform-data cmd slot data #:optional
+ (length (bytevector-length data))
+ (offset 0))
+ (SDL_PushGPUVertexUniformData (unwrap-gpu-command-buffer cmd)
+ slot
+ (bytevector->pointer data offset)
+ length))
+
+(define* (make-gpu-blit-info #:key
+ source-texture
+ (source-mip-level 0)
+ (source-layer-or-depth-plane 0)
+ (source-x 0)
+ (source-y 0)
+ (source-width 0)
+ (source-height 0)
+ destination-texture
+ (destination-mip-level 0)
+ (destination-layer-or-depth-plane 0)
+ (destination-x 0)
+ (destination-y 0)
+ (destination-width 0)
+ (destination-height 0)
+ (load-op 'dont-care)
+ (clear-color 'todo)
+ (flip-mode 'none)
+ (filter 'linear)
+ cycle?)
+ (bstruct-alloc
+ SDL_GPUBlitInfo
+ ((source texture)
+ (if source-texture
+ (unwrap-gpu-texture source-texture)
+ %null-pointer))
+ ((source mip_level) source-mip-level)
+ ((source layer_or_depth_plane) source-layer-or-depth-plane)
+ ((source x) source-x)
+ ((source y) source-y)
+ ((source w) source-width)
+ ((source h) source-height)
+ ((destination texture)
+ (if destination-texture
+ (unwrap-gpu-texture destination-texture)
+ %null-pointer))
+ ((destination mip_level) destination-mip-level)
+ ((destination layer_or_depth_plane) destination-layer-or-depth-plane)
+ ((destination x) destination-x)
+ ((destination y) destination-y)
+ ((destination w) destination-width)
+ ((destination h) destination-height)
+ (load_op (symbol->gpu-load-op load-op))
+ (flip_mode (symbol->flip-mode flip-mode))
+ (filter (symbol->gpu-filter filter))
+ (cycle (if cycle? 1 0))))
+
+(define (gpu-blit-info? obj)
+ (bstruct? SDL_GPUBlitInfo obj))
+
+(define (set-gpu-blit-info-source-texture! blit-info texture)
+ (bstruct-set! SDL_GPUBlitInfo blit-info
+ ((source texture) (unwrap-gpu-texture texture))))
+
+(define (set-gpu-blit-info-destination-texture! blit-info texture)
+ (bstruct-set! SDL_GPUBlitInfo blit-info
+ ((destination texture) (unwrap-gpu-texture texture))))
+
+(define (blit-gpu-texture cmd blit-info)
+ (SDL_BlitGPUTexture (unwrap-gpu-command-buffer cmd)
+ (bstruct->pointer SDL_GPUBlitInfo blit-info)))
+
+
+;;;
+;;; Copy passes
+;;;
+
+(define (begin-gpu-copy-pass cmd)
+ (wrap-gpu-copy-pass
+ (sdl-assert-non-null
+ 'begin-gpu-copy-pass
+ (SDL_BeginGPUCopyPass (unwrap-gpu-command-buffer cmd)))))
+
+(define (end-gpu-copy-pass pass)
+ (SDL_EndGPUCopyPass (unwrap-gpu-copy-pass pass)))
+
+(define* (upload-to-gpu-buffer pass source source-start target target-start
+ len #:optional cycle?)
+ (SDL_UploadToGPUBuffer (unwrap-gpu-copy-pass pass)
+ (bstruct-alloc-pointer
+ SDL_GPUTransferBufferLocation
+ (transfer_buffer (unwrap-gpu-transfer-buffer source))
+ (offset source-start))
+ (bstruct-alloc-pointer
+ SDL_GPUBufferRegion
+ (buffer (unwrap-gpu-buffer target))
+ (offset target-start)
+ (size len))
+ (if cycle? 1 0)))
+
+
+;;;
+;;; Render passes
+;;;
+
+(define* (make-gpu-color-target texture #:key
+ (mip-level 0)
+ (layer-or-depth-plane 0)
+ (clear-color 'todo)
+ (load-op 'load)
+ (store-op 'store)
+ resolve-texture
+ (resolve-mip-level 0)
+ (resolve-layer 0)
+ cycle?
+ cycle-resolve-texture?)
+ (bstruct-alloc
+ SDL_GPUColorTargetInfo
+ (texture (if (gpu-texture? texture)
+ (unwrap-gpu-texture texture)
+ %null-pointer))
+ (mip_level mip-level)
+ (layer_or_depth_plane layer-or-depth-plane)
+ ;; ((clear_color r) 0.6)
+ ;; ((clear_color g) 0.2)
+ ;; ((clear_color b) 0.4)
+ ;; ((clear_color a) 1.0)
+ (load_op (symbol->gpu-load-op load-op))
+ (store_op (symbol->gpu-store-op store-op))
+ (resolve_texture (if resolve-texture
+ (unwrap-gpu-texture resolve-texture)
+ %null-pointer))
+ (resolve_mip_level resolve-mip-level)
+ (resolve_layer resolve-layer)
+ (cycle (if cycle? 1 0))
+ (cycle_resolve_texture (if cycle-resolve-texture? 1 0))))
+
+(define (set-gpu-color-target-texture! color-target texture)
+ (bstruct-set! SDL_GPUColorTargetInfo color-target
+ (texture (unwrap-gpu-texture texture))))
+
+(define* (make-gpu-depth-stencil-target texture #:key
+ (clear-depth 1.0)
+ (load-op 'load)
+ (store-op 'store)
+ (stencil-load-op 'dont-care)
+ (stencil-store-op 'dont-care)
+ cycle?
+ (clear-stencil 0))
+ (bstruct-alloc
+ SDL_GPUDepthStencilTargetInfo
+ (texture (unwrap-gpu-texture texture))
+ (clear_depth clear-depth)
+ (load_op (symbol->gpu-load-op load-op))
+ (store_op (symbol->gpu-store-op store-op))
+ (stencil_load_op (symbol->gpu-load-op stencil-load-op))
+ (stencil_store_op (symbol->gpu-store-op stencil-store-op))
+ (cycle (if cycle? 1 0))
+ (clear_stencil clear-stencil)))
+
+(define* (make-gpu-buffer-binding buffer #:optional (offset 0))
+ (bstruct-alloc
+ SDL_GPUBufferBinding
+ (buffer (unwrap-gpu-buffer buffer))
+ (offset offset)))
+
+(define (begin-gpu-render-pass cmd color-targets depth-stencil-target)
+ (define color-target-size (bstruct-sizeof SDL_GPUColorTargetInfo))
+ (define num-color-targets (vector-length color-targets))
+ (define color-target-infos
+ (make-bytevector (* color-target-size num-color-targets)))
+ (do ((i 0 (1+ i)))
+ ((= i num-color-targets))
+ (let ((offset (* color-target-size i)))
+ (call-with-values
+ (lambda ()
+ (bstruct-unwrap SDL_GPUColorTargetInfo
+ (vector-ref color-targets i)))
+ (lambda (bv offset*)
+ (bytevector-copy! bv offset*
+ color-target-infos offset
+ color-target-size)))))
+ (wrap-gpu-render-pass
+ (sdl-assert-non-null
+ 'begin-gpu-render-pass
+ (SDL_BeginGPURenderPass (unwrap-gpu-command-buffer cmd)
+ (bytevector->pointer color-target-infos)
+ num-color-targets
+ (bstruct->pointer
+ SDL_GPUDepthStencilTargetInfo
+ depth-stencil-target)))))
+
+(define (end-gpu-render-pass pass)
+ (SDL_EndGPURenderPass (unwrap-gpu-render-pass pass)))
+
+(define (bind-gpu-graphics-pipeline pass pipeline)
+ (SDL_BindGPUGraphicsPipeline (unwrap-gpu-render-pass pass)
+ (unwrap-gpu-graphics-pipeline pipeline)))
+
+(define (bind-gpu-vertex-buffers pass first-slot bindings)
+ (define binding-size (bstruct-sizeof SDL_GPUBufferBinding))
+ (define num-bindings (vector-length bindings))
+ (define bindings*
+ (make-bytevector (* binding-size num-bindings)))
+ (do ((i 0 (1+ i)))
+ ((= i num-bindings))
+ (let ((offset (* binding-size i)))
+ (call-with-values (lambda ()
+ (bstruct-unwrap SDL_GPUBufferBinding
+ (vector-ref bindings i)))
+ (lambda (bv offset*)
+ (bytevector-copy! bv offset*
+ bindings* offset
+ binding-size)))))
+ (SDL_BindGPUVertexBuffers (unwrap-gpu-render-pass pass)
+ first-slot
+ (bytevector->pointer bindings*)
+ (vector-length bindings)))
+
+(define* (draw-gpu-primitives pass num-vertices #:optional
+ (num-instances 1)
+ (first-vertex 0)
+ (first-instance 0))
+ (SDL_DrawGPUPrimitives (unwrap-gpu-render-pass pass)
+ num-vertices
+ num-instances
+ first-vertex
+ first-instance))
+
+
+;;;
+;;; Compute passes
+;;;
diff --git a/sdl3/guardian.scm b/sdl3/guardian.scm
new file mode 100644
index 0000000..d0a812b
--- /dev/null
+++ b/sdl3/guardian.scm
@@ -0,0 +1,30 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; SDL3 foreign object guardian.
+;;
+;;; Code:
+
+(define-module (sdl3 guardian)
+ #:export (sdl-guardian
+ sdl-protect))
+
+(define sdl-guardian (make-guardian))
+
+(define (sdl-protect obj)
+ (sdl-guardian obj)
+ obj)
diff --git a/sdl3/video.scm b/sdl3/video.scm
new file mode 100644
index 0000000..35a37c8
--- /dev/null
+++ b/sdl3/video.scm
@@ -0,0 +1,85 @@
+;;; guile-sdl3 -- Scheme bindings for SDL3
+;;; Copyright © 2024 David Thompson <dthompson2@worcester.edu>
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;; Commentary:
+;;
+;; SDL3 display and window management.
+;;
+;;; Code:
+
+(define-module (sdl3 video)
+ #:use-module (rnrs bytevectors)
+ #:use-module (sdl3 bindings video)
+ #:use-module (sdl3 errors)
+ #:use-module (system foreign)
+ #:export (make-window
+ destroy-window!
+ window-size-in-pixels)
+ #:re-export (window?
+ window-destroyed?))
+
+(define* (make-window title width height #:key
+ opengl?
+ vulkan?
+ metal?
+ (shown? #t)
+ fullscreen?
+ borderless?
+ transparent?
+ resizable?
+ (focusable? #t)
+ high-pixel-density?
+ always-on-top?
+ utility?)
+ "Open a window with the specified @var{title} and dimensions
+@var{width} by @var{height} pixels and return a handle to that window."
+ (wrap-window
+ (sdl-assert-non-null
+ 'make-window
+ (SDL_CreateWindow (string->pointer title)
+ width height
+ (logior
+ (if opengl? SDL_WINDOW_OPENGL 0)
+ (if vulkan? SDL_WINDOW_VULKAN 0)
+ (if metal? SDL_WINDOW_METAL 0)
+ (if fullscreen? SDL_WINDOW_FULLSCREEN 0)
+ (if shown? 0 SDL_WINDOW_HIDDEN)
+ (if borderless? SDL_WINDOW_BORDERLESS 0)
+ (if transparent? SDL_WINDOW_TRANSPARENT 0)
+ (if resizable? SDL_WINDOW_RESIZABLE 0)
+ (if focusable? 0 SDL_WINDOW_NOT_FOCUSABLE)
+ (if high-pixel-density? SDL_WINDOW_HIGH_PIXEL_DENSITY 0)
+ (if always-on-top? SDL_WINDOW_ALWAYS_ON_TOP 0)
+ (if utility? SDL_WINDOW_UTILITY 0))))))
+
+;; FIXME: SDL_DestroyWindow recursively destroys child windows. Do we
+;; need to keep track of those in Scheme, then?
+(define (destroy-window! window)
+ "Close @var{window} and make handle unusable for further window
+management calls."
+ (unless (window-destroyed? window)
+ (SDL_DestroyWindow (unwrap-window window))
+ (set-window-destroyed! window #t)))
+
+(define (window-size-in-pixels window)
+ (let* ((size (sizeof int))
+ (bv (make-bytevector (* size 2))))
+ (sdl-assert
+ 'window-size-in-pixels
+ (SDL_GetWindowSizeInPixels (unwrap-window window)
+ (bytevector->pointer bv)
+ (bytevector->pointer bv size)))
+ (values (bytevector-sint-ref bv 0 (native-endianness) size)
+ (bytevector-sint-ref bv size (native-endianness) size))))