Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,83 @@
|
||||
## Description
|
||||
|
||||
`sokol` is a thin wrapper around [sokol](https://github.com/floooh/sokol),
|
||||
which in turn is a library of "Simple STB-style cross-platform libraries
|
||||
for C and C++, written in C.", that provide access to graphics/audio/input
|
||||
processing.
|
||||
|
||||
Each `.h` file in the sokol source code is well-documented as can be seen here:
|
||||
|
||||
[sokol_audio.h](https://github.com/floooh/sokol/blob/master/sokol_audio.h)
|
||||
|
||||
## Example from `@VEXEROOT/examples/sokol/sounds/simple_sin_tones.v`
|
||||
|
||||
```v cgen
|
||||
import time
|
||||
import math
|
||||
import sokol.audio
|
||||
|
||||
const sw = time.new_stopwatch()
|
||||
const sw_start_ms = sw.elapsed().milliseconds()
|
||||
|
||||
@[inline]
|
||||
fn sintone(periods int, frame int, num_frames int) f32 {
|
||||
return math.sinf(f32(periods) * (2 * math.pi) * f32(frame) / f32(num_frames))
|
||||
}
|
||||
|
||||
fn my_audio_stream_callback(buffer &f32, num_frames int, num_channels int) {
|
||||
ms := sw.elapsed().milliseconds() - sw_start_ms
|
||||
unsafe {
|
||||
mut soundbuffer := buffer
|
||||
for frame := 0; frame < num_frames; frame++ {
|
||||
for ch := 0; ch < num_channels; ch++ {
|
||||
idx := frame * num_channels + ch
|
||||
if ms < 250 {
|
||||
soundbuffer[idx] = 0.5 * sintone(20, frame, num_frames)
|
||||
} else if ms < 300 {
|
||||
soundbuffer[idx] = 0.5 * sintone(25, frame, num_frames)
|
||||
} else if ms < 1500 {
|
||||
soundbuffer[idx] *= sintone(22, frame, num_frames)
|
||||
} else {
|
||||
soundbuffer[idx] = 0.5 * sintone(25, frame, num_frames)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
audio.setup(
|
||||
stream_cb: my_audio_stream_callback
|
||||
)
|
||||
time.sleep(2000 * time.millisecond)
|
||||
audio.shutdown()
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting sokol apps
|
||||
|
||||
A common problem, if you draw a lot of primitive elements in the same frame,
|
||||
is that there is a chance that your program can exceed the maximum
|
||||
allowed amount of vertices and commands, imposed by `sokol`.
|
||||
|
||||
The symptom is that your frame will be suddenly black, after it
|
||||
becomes more complex.
|
||||
|
||||
Sokol's default for vertices is 131072.
|
||||
Sokol's default for commands is 32768.
|
||||
|
||||
To solve that, you can try adding these lines at the top of your program:
|
||||
`#flag -D_SGL_DEFAULT_MAX_VERTICES=4194304`
|
||||
`#flag -D_SGL_DEFAULT_MAX_COMMANDS=65536`
|
||||
You can see an example of that in:
|
||||
https://github.com/vlang/v/blob/master/examples/gg/examples/gg/many_thousands_of_circles_overriding_max_vertices.v
|
||||
|
||||
Another approach to that problem, is to draw everything yourself in a streaming
|
||||
texture, then upload that streaming texture as a single draw command to the GPU.
|
||||
You can see an example of that done in:
|
||||
https://github.com/vlang/v/blob/master/examples/gg/random.v
|
||||
and in:
|
||||
https://github.com/vlang/v/blob/master/examples/gg/random_stars.v
|
||||
|
||||
A third approach, is to only upload your changing inputs to the GPU, and do all
|
||||
the calculations and drawing there in shaders.
|
||||
@@ -0,0 +1,229 @@
|
||||
module audio
|
||||
|
||||
import sokol.memory
|
||||
|
||||
$if linux {
|
||||
// provide a nicer error for the user that does not have ALSA installed
|
||||
#include <alsa/asoundlib.h> # Please install the `libasound2-dev` package
|
||||
}
|
||||
|
||||
$if openbsd {
|
||||
$compile_error('sokol/audio not supported on OpenBSD')
|
||||
}
|
||||
|
||||
#flag -I @VEXEROOT/thirdparty/sokol
|
||||
// FreeBSD requires the audio/alsa-lib to be installed
|
||||
#flag freebsd -I/usr/local/include
|
||||
|
||||
@[use_once]
|
||||
#define SOKOL_IMPL
|
||||
#include "sokol_audio.h"
|
||||
#flag linux -lasound -lpthread
|
||||
#flag darwin -framework AudioToolbox
|
||||
#flag windows -lole32
|
||||
#flag freebsd -L/usr/local/lib
|
||||
#flag freebsd -lasound
|
||||
#flag android -laaudio
|
||||
|
||||
// callback function for `stream_cb` in [[C.saudio_desc](#C.saudio_desc)] when calling [audio.setup()](#setup)
|
||||
//
|
||||
// sokol callback functions run in a separate thread
|
||||
//
|
||||
// This function will be called with a reference to the C buffer and the maximum number of frames and channels
|
||||
// the audio backend is expecting in its buffer.
|
||||
//
|
||||
// Terms:
|
||||
// - *sample* - a 32-bit floating point number from `-1.0` to `+1.0` representing the waveform amplitude at that instant
|
||||
// - *frame* - one sample for each channel at that instant
|
||||
//
|
||||
// To determine the number of samples expected, do `num_frames * num_channels`.
|
||||
// Then, write up to that many `f32` samples into `buffer` using unsafe operations.
|
||||
//
|
||||
// Do not write more data to the buffer than it is requesting, but you may write less. The buffer is initialized with
|
||||
// zeroes, so unwritten data will result in audio silence.
|
||||
// Example body: unsafe { C.memcpy(buffer, &samples, samples.len * int(sizeof(f32))) }
|
||||
// Example body: unsafe { mut b := buffer; for i, sample in samples { b[i] = sample } }
|
||||
pub type FNStreamingCB = fn (buffer &f32, num_frames int, num_channels int)
|
||||
|
||||
// callback function for `stream_userdata_cb` to use in `C.saudio_desc` when calling [audio.setup()](#setup)
|
||||
// This function operates the same way as [[FNStreamingCB](#FNStreamingCB)] but it passes customizable `user_data` to the
|
||||
// callback. This is the method to use if your audio data is stored in a struct or array. Identify the
|
||||
// `user_data` when you call `audio.setup()` and that object will be passed to the callback as the last arg.
|
||||
// Note: Sokol's callback functions run in a separate thread.
|
||||
// Example: previously_parsed_wavfile_bytes := [f32(0),0,0,0]; mycallback := fn (buffer &f32, num_frames int, num_channels int, mut sb []f32) {}; mut soundbuffer := []f32{}; soundbuffer << previously_parsed_wavfile_bytes; audio.setup(stream_userdata_cb: mycallback, user_data: soundbuffer.data);
|
||||
pub type FnStreamingCBWithUserData = fn (buffer &f32, num_frames int, num_channels int, user_data voidptr)
|
||||
|
||||
pub fn (x FNStreamingCB) str() string {
|
||||
return '&FNStreamingCB{ ${ptr_str(x)} }'
|
||||
}
|
||||
|
||||
pub fn (x FnStreamingCBWithUserData) str() string {
|
||||
return '&FnStreamingCBWithUserData{ ${ptr_str(x)} }'
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.saudio_allocator {
|
||||
pub mut:
|
||||
alloc_fn memory.FnAllocatorAlloc
|
||||
free_fn memory.FnAllocatorFree
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.saudio_logger {
|
||||
pub mut:
|
||||
func memory.FnLogCb
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
// only one of `stream_cb` or `stream_userdata_cb` should be used
|
||||
//
|
||||
// default values (internal to sokol C library):
|
||||
//
|
||||
// | variable | default | note |
|
||||
// | :----------- | -------: | :--------- |
|
||||
// | sample_rate | 44100 | higher sample rates take more memory but are higher quality |
|
||||
// | num_channels | 1 | for stereo sound, this should be 2 |
|
||||
// | buffer_frames | 2048 | buffer size in frames, larger is more latency, smaller means higher CPU |
|
||||
// | packet_frames | 128 | push model only, number of frames that will be pushed in each packet |
|
||||
// | num_packets | 64 | for push model only, number of packets in the backend ringbuffer |
|
||||
@[params; typedef]
|
||||
pub struct C.saudio_desc {
|
||||
pub:
|
||||
sample_rate int
|
||||
num_channels int
|
||||
buffer_frames int
|
||||
packet_frames int
|
||||
num_packets int
|
||||
stream_cb FNStreamingCB
|
||||
stream_userdata_cb FnStreamingCBWithUserData
|
||||
pub mut:
|
||||
user_data voidptr
|
||||
allocator C.saudio_allocator
|
||||
logger C.saudio_logger
|
||||
}
|
||||
|
||||
fn C.saudio_setup(const_desc &C.saudio_desc)
|
||||
|
||||
fn C.saudio_shutdown()
|
||||
|
||||
fn C.saudio_isvalid() bool
|
||||
|
||||
fn C.saudio_userdata() voidptr
|
||||
|
||||
fn C.saudio_query_desc() C.saudio_desc
|
||||
|
||||
fn C.saudio_sample_rate() i32
|
||||
|
||||
fn C.saudio_buffer_frames() i32
|
||||
|
||||
fn C.saudio_channels() i32
|
||||
|
||||
fn C.saudio_suspended() bool
|
||||
|
||||
fn C.saudio_expect() i32
|
||||
|
||||
fn C.saudio_push(const_frames &f32, num_frames i32) i32
|
||||
|
||||
// setup - setup sokol-audio
|
||||
pub fn setup(desc &C.saudio_desc) {
|
||||
if desc.allocator.alloc_fn == unsafe { nil } && desc.allocator.free_fn == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.allocator.alloc_fn = memory.salloc
|
||||
desc.allocator.free_fn = memory.sfree
|
||||
desc.allocator.user_data = voidptr(0x100a0d10)
|
||||
}
|
||||
}
|
||||
if desc.logger.func == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.logger.func = memory.slog
|
||||
}
|
||||
}
|
||||
C.saudio_setup(desc)
|
||||
}
|
||||
|
||||
// shutdown - shutdown sokol-audio
|
||||
pub fn shutdown() {
|
||||
C.saudio_shutdown()
|
||||
}
|
||||
|
||||
// is_valid - true after setup if audio backend was successfully initialized
|
||||
pub fn is_valid() bool {
|
||||
return C.saudio_isvalid()
|
||||
}
|
||||
|
||||
// userdata - return the saudio_desc.user_data pointer
|
||||
pub fn user_data() voidptr {
|
||||
return C.saudio_userdata()
|
||||
}
|
||||
|
||||
// query - return a copy of the original saudio_desc struct
|
||||
pub fn query() C.saudio_desc {
|
||||
return C.saudio_query_desc()
|
||||
}
|
||||
|
||||
// sample_rate - return the actual sample rate
|
||||
pub fn sample_rate() int {
|
||||
return C.saudio_sample_rate()
|
||||
}
|
||||
|
||||
// buffer_frames - return the actual backend buffer size in number of frames
|
||||
pub fn buffer_frames() int {
|
||||
return C.saudio_buffer_frames()
|
||||
}
|
||||
|
||||
// channels - return the actual number of channels
|
||||
pub fn channels() int {
|
||||
return C.saudio_channels()
|
||||
}
|
||||
|
||||
// suspended returns true if audio context is currently suspended
|
||||
// (only in WebAudio backend, all other backends return false)
|
||||
pub fn suspended() bool {
|
||||
return C.saudio_suspended()
|
||||
}
|
||||
|
||||
// expect - get current number of frames to fill packet queue; use in combination with audio.push
|
||||
pub fn expect() int {
|
||||
return C.saudio_expect()
|
||||
}
|
||||
|
||||
// push - push sample frames from main thread, returns number of frames actually pushed
|
||||
pub fn push(frames &f32, num_frames int) int {
|
||||
return C.saudio_push(frames, num_frames)
|
||||
}
|
||||
|
||||
// fclamp - helper function to 'clamp' a number to a certain range
|
||||
// Example: sample := f32(3.14); realsample := audio.fclamp(sample, -1.0, 1.0); assert realsample == 1.0
|
||||
@[inline]
|
||||
pub fn fclamp(x f32, flo f32, fhi f32) f32 {
|
||||
if x > fhi {
|
||||
return fhi
|
||||
}
|
||||
if x < flo {
|
||||
return flo
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// min - helper function to return the smaller of two numbers
|
||||
//
|
||||
// NOTE: math.min returns `f32` values, this returns `int` values
|
||||
// Example: println(audio.min(1, 5))
|
||||
pub fn min(x int, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
// max - helper function to return the larger of two numbers
|
||||
//
|
||||
// NOTE: math.max returns `f32` values, this returns `int` values
|
||||
// Example: println(audio.max(1, 5))
|
||||
pub fn max(x int, y int) int {
|
||||
if x < y {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
module c
|
||||
|
||||
import sokol.memory as _
|
||||
|
||||
#flag -I @VEXEROOT/thirdparty/sokol
|
||||
#flag -I @VEXEROOT/thirdparty/sokol/util
|
||||
#flag freebsd -I /usr/local/include
|
||||
#flag darwin -fobjc-arc
|
||||
|
||||
// Platform-specific library linking
|
||||
// X11 is the default on Linux
|
||||
// Use `-d sokol_wayland` to enable Wayland support
|
||||
#flag linux -DSOKOL_GLCORE
|
||||
$if sokol_wayland ? {
|
||||
#flag linux -lwayland-client -lwayland-egl -lxkbcommon -lxkbcommon-x11 -lEGL -lGL -lpthread -lm -ldl -lX11 -lXi -lXcursor
|
||||
} $else {
|
||||
// EGL is used instead of GLX on X11 to get consistent vsync under XWayland.
|
||||
// GLX vsync is often ignored by XWayland compositors, causing frame pacing
|
||||
// jitter. EGL honours the swap interval reliably on both native X11 and
|
||||
// XWayland sessions.
|
||||
#flag linux -lX11 -lXi -lXcursor -lEGL -lGL -lpthread -lm -ldl
|
||||
}
|
||||
#flag freebsd -DSOKOL_GLCORE
|
||||
#flag freebsd -L/usr/local/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag openbsd -DSOKOL_GLCORE
|
||||
#flag openbsd -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag windows -DSOKOL_GLCORE
|
||||
#flag windows -lgdi32
|
||||
|
||||
$if windows {
|
||||
#flag windows -lopengl32
|
||||
$if msvc {
|
||||
$if livemain ? {
|
||||
#define SOKOL_DLL
|
||||
}
|
||||
$if sharedlive ? {
|
||||
#define SOKOL_DLL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that -lm is needed *only* for sokol_gl.h's usage of sqrtf(),
|
||||
// but without -lm, this fails:
|
||||
// `v -cc gcc ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||
// With tcc, this succeeds with or without -lm:
|
||||
// `v ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||
$if !tinyc {
|
||||
#flag linux -lm
|
||||
}
|
||||
|
||||
// METAL
|
||||
$if macos {
|
||||
$if darwin_sokol_glcore33 ? {
|
||||
#flag darwin -DSOKOL_GLCORE -framework OpenGL -framework Cocoa -framework QuartzCore
|
||||
} $else {
|
||||
#flag -DSOKOL_METAL
|
||||
#flag -framework Metal -framework Cocoa -framework MetalKit -framework QuartzCore
|
||||
}
|
||||
}
|
||||
$if ios {
|
||||
#flag -DSOKOL_METAL
|
||||
#flag -framework Foundation -framework Metal -framework MetalKit -framework UIKit
|
||||
}
|
||||
|
||||
$if emscripten ? {
|
||||
#flag -DSOKOL_GLES3
|
||||
#flag -DSOKOL_NO_ENTRY
|
||||
#flag -s ERROR_ON_UNDEFINED_SYMBOLS=0
|
||||
#flag -s USE_WEBGL2
|
||||
$if !prod {
|
||||
#flag -s ASSERTIONS=1
|
||||
}
|
||||
$if prod {
|
||||
#flag -s ASSERTIONS=0
|
||||
}
|
||||
// See https://emscripten.org/docs/tools_reference/settings_reference.html#modularize
|
||||
// Note that it makes it impossible to use `v -os wasm32_emscripten -o file.html program.v` , due to:
|
||||
// https://github.com/emscripten-core/emscripten/issues/7950
|
||||
// #flag -s MODULARIZE
|
||||
}
|
||||
|
||||
// D3D
|
||||
//#flag windows -DSOKOL_D3D11
|
||||
#flag windows -DSOKOL_GLCORE
|
||||
|
||||
// for simplicity, all header includes are here because import order matters and we dont have any way
|
||||
// to ensure import order with V yet
|
||||
|
||||
// TODO: should not be defined for android graphic (apk/aab using sokol) builds, but we have no ways to undefine
|
||||
//#define SOKOL_NO_ENTRY
|
||||
#flag linux -DSOKOL_NO_ENTRY
|
||||
#flag darwin -DSOKOL_NO_ENTRY
|
||||
#flag windows -DSOKOL_NO_ENTRY
|
||||
#flag windows -DSOKOL_WIN32_FORCE_MAIN
|
||||
#flag freebsd -DSOKOL_NO_ENTRY
|
||||
#flag openbsd -DSOKOL_NO_ENTRY
|
||||
#flag solaris -DSOKOL_NO_ENTRY
|
||||
// TODO: end
|
||||
|
||||
#flag linux -ldl
|
||||
|
||||
// To allow for thirdparty initializing window / acceleration contexts
|
||||
// but still be able to use sokol.gfx e.g. SDL+sokol_gfx
|
||||
$if !no_sokol_app ? {
|
||||
$if linux && sokol_wayland ? {
|
||||
// Enable Wayland on Linux (when explicitly enabled with -d sokol_wayland)
|
||||
#define SOKOL_WAYLAND
|
||||
#flag -I@VEXEROOT/thirdparty/sokol
|
||||
} $else $if linux {
|
||||
// Explicitly disable Wayland on Linux when not using sokol_wayland
|
||||
#define SOKOL_DISABLE_WAYLAND
|
||||
// Force EGL instead of GLX so that eglSwapBuffers provides consistent
|
||||
// vsync pacing on both native X11 and XWayland sessions.
|
||||
#define SOKOL_FORCE_EGL
|
||||
}
|
||||
|
||||
$if macos {
|
||||
$if sharedlive ? {
|
||||
} $else {
|
||||
// The live-reload dylib should reuse the host app's sokol_app symbols on macOS.
|
||||
#define SOKOL_APP_IMPL
|
||||
}
|
||||
} $else $if windows {
|
||||
$if sharedlive ? {
|
||||
} $else {
|
||||
// On Windows, the live-reload DLL links back to the host executable's
|
||||
// import library, so it should not embed its own sokol_app backend.
|
||||
#define SOKOL_APP_IMPL
|
||||
}
|
||||
} $else {
|
||||
#define SOKOL_APP_IMPL
|
||||
}
|
||||
|
||||
@[use_once]
|
||||
#include "sokol_app.h"
|
||||
}
|
||||
|
||||
$if windows && sharedlive ? {
|
||||
} $else {
|
||||
@[use_once]
|
||||
#define SOKOL_GFX_IMPL
|
||||
}
|
||||
#define SOKOL_NO_DEPRECATED
|
||||
#include "sokol_gfx.h"
|
||||
|
||||
$if windows && sharedlive ? {
|
||||
} $else {
|
||||
@[use_once]
|
||||
#define SOKOL_IMPL
|
||||
}
|
||||
#include "util/sokol_gl.h"
|
||||
|
||||
#include "sokol_v.post.h"
|
||||
@@ -0,0 +1,12 @@
|
||||
module f
|
||||
|
||||
import fontstash as _
|
||||
import sokol.c as _
|
||||
|
||||
#flag linux -I.
|
||||
|
||||
//#include "ft2build.h"
|
||||
|
||||
@[use_once]
|
||||
#define SOKOL_FONTSTASH_IMPL
|
||||
#include "util/sokol_fontstash.h"
|
||||
@@ -0,0 +1,386 @@
|
||||
module gfx
|
||||
|
||||
pub enum Backend {
|
||||
glcore33
|
||||
gles3
|
||||
d3d11
|
||||
metal_ios
|
||||
metal_macos
|
||||
metal_simulator
|
||||
wgpu
|
||||
dummy
|
||||
}
|
||||
|
||||
// PixelFormat is C.sg_pixel_format
|
||||
pub enum PixelFormat as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
none
|
||||
|
||||
r8
|
||||
r8sn
|
||||
r8ui
|
||||
r8si
|
||||
|
||||
r16
|
||||
r16sn
|
||||
r16ui
|
||||
r16si
|
||||
r16f
|
||||
rg8
|
||||
rg8sn
|
||||
rg8ui
|
||||
rg8si
|
||||
|
||||
r32ui
|
||||
r32si
|
||||
r32f
|
||||
rg16
|
||||
rg16sn
|
||||
rg16ui
|
||||
rg16si
|
||||
rg16f
|
||||
rgba8
|
||||
srgb8a8
|
||||
rgba8sn
|
||||
rgba8ui
|
||||
rgba8si
|
||||
bgra8
|
||||
rgb10a2
|
||||
rg11b10f
|
||||
rgb9e5
|
||||
|
||||
rg32ui
|
||||
rg32si
|
||||
rg32f
|
||||
rgba16
|
||||
rgba16sn
|
||||
rgba16ui
|
||||
rgba16si
|
||||
rgba16f
|
||||
|
||||
rgba32ui
|
||||
rgba32si
|
||||
rgba32f
|
||||
|
||||
depth
|
||||
depth_stencil
|
||||
|
||||
bc1_rgba
|
||||
bc2_rgba
|
||||
bc3_rgba
|
||||
bc3_srgba
|
||||
bc4_r
|
||||
bc4_rsn
|
||||
bc5_rg
|
||||
bc5_rgsn
|
||||
bc6h_rgbf
|
||||
bc6h_rgbuf
|
||||
bc7_rgba
|
||||
bc7_srgba
|
||||
pvrtc_rgb_2bpp // deprecated
|
||||
pvrtc_rgb_4bpp // deprecated
|
||||
pvrtc_rgba_2bpp // deprecated
|
||||
pvrtc_rgba_4bpp // deprecated
|
||||
etc2_rgb8
|
||||
etc2_srgb8
|
||||
etc2_rgb8a1
|
||||
etc2_rgba8
|
||||
etc2_srgb8a8
|
||||
eac_r11
|
||||
eac_r11sn
|
||||
eac_rg11
|
||||
eac_rg11sn
|
||||
astc_4x4_rgba
|
||||
astc_4x4_srgba
|
||||
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum ResourceState as u32 {
|
||||
initial
|
||||
alloc
|
||||
valid
|
||||
failed
|
||||
invalid
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum Usage as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
immutable
|
||||
dynamic
|
||||
stream
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum BufferType as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
vertexbuffer
|
||||
indexbuffer
|
||||
storagebuffer
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum IndexType as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
none
|
||||
uint16
|
||||
uint32
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum ImageType as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
_2d
|
||||
cube
|
||||
_3d
|
||||
array
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum ImageSampleType as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
float
|
||||
depth
|
||||
sint
|
||||
uint
|
||||
unfilterable_float
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum SamplerType as u32 {
|
||||
_default
|
||||
filtering
|
||||
nonfiltering
|
||||
comparison
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum CubeFace as u32 {
|
||||
pos_x
|
||||
neg_x
|
||||
pos_y
|
||||
neg_y
|
||||
pos_z
|
||||
neg_z
|
||||
num
|
||||
_force_u32 = 0x7fffffff
|
||||
}
|
||||
|
||||
pub enum ShaderStage as u32 {
|
||||
vs
|
||||
fs
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum PrimitiveType as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
points
|
||||
lines
|
||||
line_strip
|
||||
triangles
|
||||
triangle_strip
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum Filter as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
none
|
||||
nearest
|
||||
linear
|
||||
_num
|
||||
_force_u32 = 0x7fffffff
|
||||
}
|
||||
|
||||
pub enum Wrap as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
repeat // The default wrap mode.
|
||||
clamp_to_edge
|
||||
clamp_to_border // not supported on all backends and platforms. To check for support, call sg_query_features(), and check the "clamp_to_border" boolean in the returned sg_features struct. Platforms which don't support SG_WRAP_CLAMP_TO_BORDER will silently fall back to clamp_to_edge without a validation error.
|
||||
mirrored_repeat
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum BorderColor as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
transparent_black
|
||||
opaque_black
|
||||
opaque_white
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum VertexFormat as u32 {
|
||||
invalid
|
||||
float
|
||||
float2
|
||||
float3
|
||||
float4
|
||||
byte4
|
||||
byte4n // normalized
|
||||
ubyte4
|
||||
ubyte4n
|
||||
short2
|
||||
short2n
|
||||
ushort2n
|
||||
short4
|
||||
short4n
|
||||
ushort4n
|
||||
uint10_n2
|
||||
half2
|
||||
half4
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum VertexStep as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
per_vertex
|
||||
per_instance
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum UniformType as u32 {
|
||||
invalid
|
||||
float
|
||||
float2
|
||||
float3
|
||||
float4
|
||||
int
|
||||
int2
|
||||
int3
|
||||
int4
|
||||
mat4
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum CullMode as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
none
|
||||
front
|
||||
back
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
// FaceWindin is C.sg_face_winding
|
||||
pub enum FaceWinding as u32 {
|
||||
default // value 0 reserved for default-init
|
||||
ccw
|
||||
cw
|
||||
num
|
||||
force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum CompareFunc as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
never
|
||||
less
|
||||
equal
|
||||
less_equal
|
||||
greater
|
||||
not_equal
|
||||
greater_equal
|
||||
always
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum StencilOp as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
keep
|
||||
zero
|
||||
replace
|
||||
incr_clamp
|
||||
decr_clamp
|
||||
invert
|
||||
incr_wrap
|
||||
decr_wrap
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum BlendFactor as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
zero
|
||||
one
|
||||
src_color
|
||||
one_minus_src_color
|
||||
src_alpha
|
||||
one_minus_src_alpha
|
||||
dst_color
|
||||
one_minus_dst_color
|
||||
dst_alpha
|
||||
one_minus_dst_alpha
|
||||
src_alpha_saturated
|
||||
blend_color
|
||||
one_minus_blend_color
|
||||
blend_alpha
|
||||
one_minus_blend_alpha
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum BlendOp as u32 {
|
||||
_default // value 0 reserved for default-init
|
||||
add
|
||||
subtract
|
||||
reverse_subtract
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum ColorMask as u32 {
|
||||
_default = 0 // value 0 reserved for default-init
|
||||
none = 0x10 // special value for 'all channels disabled
|
||||
r = 1
|
||||
g = 2
|
||||
rg = 3
|
||||
b = 4
|
||||
rb = 5
|
||||
gb = 6
|
||||
rgb = 7
|
||||
a = 8
|
||||
ra = 9
|
||||
ga = 0xa
|
||||
rga = 0xb
|
||||
ba = 0xc
|
||||
rba = 0xd
|
||||
gba = 0xe
|
||||
rgba = 0xf
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum LoadAction as u32 {
|
||||
_default
|
||||
clear
|
||||
load
|
||||
dontcare
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum StoreAction as u32 {
|
||||
_default
|
||||
store
|
||||
dontcare
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
|
||||
pub enum UniformLayout as u32 {
|
||||
uniformlayout_default = 0 // value 0 reserved for default-init
|
||||
uniformlayout_native // default: layout depends on currently active backend
|
||||
uniformlayout_std140 // std140: memory layout according to std140
|
||||
_num
|
||||
_force_u32 = 0x7FFFFFFF
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
module gfx
|
||||
|
||||
import sokol.c as _
|
||||
import sokol.memory
|
||||
|
||||
pub const version = 1
|
||||
|
||||
// setup initialises the SOKOL's gfx library, based on the information passed in `desc`
|
||||
pub fn setup(desc &Desc) {
|
||||
if desc.allocator.alloc_fn == unsafe { nil } && desc.allocator.free_fn == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.allocator.alloc_fn = memory.salloc
|
||||
desc.allocator.free_fn = memory.sfree
|
||||
desc.allocator.user_data = voidptr(0x1006fec5)
|
||||
}
|
||||
}
|
||||
if desc.logger.func == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.logger.func = memory.slog
|
||||
}
|
||||
}
|
||||
C.sg_setup(desc)
|
||||
}
|
||||
|
||||
// shutdown tells the SOKOL's gfx library to shutdown, and release the resources it is using
|
||||
pub fn shutdown() {
|
||||
C.sg_shutdown()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn is_valid() bool {
|
||||
return C.sg_isvalid()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
fn ensure_initialized(op string) {
|
||||
if is_valid() {
|
||||
return
|
||||
}
|
||||
panic('sokol.gfx is not initialized; call gfx.setup(...) before ${op}')
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn reset_state_cache() {
|
||||
C.sg_reset_state_cache()
|
||||
}
|
||||
|
||||
// resource creation, destruction and updating
|
||||
// make_buffer creates a GPU buffer.
|
||||
// make_buffer requires `gfx.setup(...)` to have completed first.
|
||||
@[inline]
|
||||
pub fn make_buffer(desc &BufferDesc) Buffer {
|
||||
ensure_initialized('gfx.make_buffer(...)')
|
||||
return C.sg_make_buffer(desc)
|
||||
}
|
||||
|
||||
// make_image creates a GPU image.
|
||||
// make_image requires `gfx.setup(...)` to have completed first.
|
||||
@[inline]
|
||||
pub fn make_image(desc &ImageDesc) Image {
|
||||
ensure_initialized('gfx.make_image(...)')
|
||||
return C.sg_make_image(desc)
|
||||
}
|
||||
|
||||
// make_sampler creates a GPU sampler.
|
||||
// make_sampler requires `gfx.setup(...)` to have completed first.
|
||||
@[inline]
|
||||
pub fn make_sampler(desc &SamplerDesc) Sampler {
|
||||
ensure_initialized('gfx.make_sampler(...)')
|
||||
return C.sg_make_sampler(desc)
|
||||
}
|
||||
|
||||
// make_shader creates a GPU shader.
|
||||
// make_shader requires `gfx.setup(...)` to have completed first.
|
||||
@[inline]
|
||||
pub fn make_shader(desc &ShaderDesc) Shader {
|
||||
ensure_initialized('gfx.make_shader(...)')
|
||||
return C.sg_make_shader(desc)
|
||||
}
|
||||
|
||||
// make_pipeline creates a GPU pipeline.
|
||||
// make_pipeline requires `gfx.setup(...)` to have completed first.
|
||||
@[inline]
|
||||
pub fn make_pipeline(desc &PipelineDesc) Pipeline {
|
||||
ensure_initialized('gfx.make_pipeline(...)')
|
||||
return C.sg_make_pipeline(desc)
|
||||
}
|
||||
|
||||
// make_attachments creates an `Attachments` instance from `const_desc`.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn make_attachments(const_desc &AttachmentsDesc) Attachments {
|
||||
ensure_initialized('gfx.make_attachments(...)')
|
||||
return C.sg_make_attachments(const_desc)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_buffer(buf Buffer) {
|
||||
C.sg_destroy_buffer(buf)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_image(img Image) {
|
||||
C.sg_destroy_image(img)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_sampler(smp Sampler) {
|
||||
C.sg_destroy_sampler(smp)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_shader(shd Shader) {
|
||||
C.sg_destroy_shader(shd)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_pipeline(pip Pipeline) {
|
||||
C.sg_destroy_pipeline(pip)
|
||||
}
|
||||
|
||||
// destroy_attachments destroys the `atts` `Attachments`
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn destroy_attachments(atts Attachments) {
|
||||
C.sg_destroy_attachments(atts)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn update_buffer(buf Buffer, data &Range) {
|
||||
C.sg_update_buffer(buf, data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn update_image(img Image, data &ImageData) {
|
||||
C.sg_update_image(img, data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn append_buffer(buf Buffer, data &Range) int {
|
||||
return C.sg_append_buffer(buf, data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_buffer_overflow(buf Buffer) bool {
|
||||
return C.sg_query_buffer_overflow(buf)
|
||||
}
|
||||
|
||||
// rendering functions
|
||||
|
||||
// begin_pass begins a rendering pass.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn begin_pass(const_pass &Pass) {
|
||||
C.sg_begin_pass(const_pass)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn apply_viewport(x int, y int, width int, height int, origin_top_left bool) {
|
||||
C.sg_apply_viewport(x, y, width, height, origin_top_left)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn apply_scissor_rect(x int, y int, width int, height int, origin_top_left bool) {
|
||||
C.sg_apply_scissor_rect(x, y, width, height, origin_top_left)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn apply_pipeline(pip Pipeline) {
|
||||
C.sg_apply_pipeline(pip)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn apply_bindings(bindings &Bindings) {
|
||||
C.sg_apply_bindings(bindings)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn apply_uniforms(stage ShaderStage, ub_index int, data &Range) {
|
||||
C.sg_apply_uniforms(stage, ub_index, data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn draw(base_element int, num_elements int, num_instances int) {
|
||||
C.sg_draw(base_element, num_elements, num_instances)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn end_pass() {
|
||||
C.sg_end_pass()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn commit() {
|
||||
C.sg_commit()
|
||||
}
|
||||
|
||||
// getting information
|
||||
@[inline]
|
||||
pub fn query_desc() Desc {
|
||||
return C.sg_query_desc()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_backend() Backend {
|
||||
unsafe {
|
||||
return Backend(C.sg_query_backend())
|
||||
}
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_features() Features {
|
||||
return C.sg_query_features()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_limits() Limits {
|
||||
return C.sg_query_limits()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_pixelformat(fmt PixelFormat) PixelFormatInfo {
|
||||
return C.sg_query_pixelformat(fmt)
|
||||
}
|
||||
|
||||
// get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)
|
||||
@[inline]
|
||||
pub fn query_buffer_state(buf Buffer) ResourceState {
|
||||
return ResourceState(C.sg_query_buffer_state(buf))
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_image_state(img Image) ResourceState {
|
||||
return ResourceState(C.sg_query_image_state(img))
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_shader_state(shd Shader) ResourceState {
|
||||
return ResourceState(C.sg_query_shader_state(shd))
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_pipeline_state(pip Pipeline) ResourceState {
|
||||
return ResourceState(C.sg_query_pipeline_state(pip))
|
||||
}
|
||||
|
||||
// query_attachments_state returns the current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn query_attachments_state(atts Attachments) ResourceState {
|
||||
return ResourceState(C.sg_query_attachments_state(atts))
|
||||
}
|
||||
|
||||
// get runtime information about a resource
|
||||
@[inline]
|
||||
pub fn query_buffer_info(buf Buffer) BufferInfo {
|
||||
return C.sg_query_buffer_info(buf)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_image_info(img Image) ImageInfo {
|
||||
return C.sg_query_image_info(img)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_shader_info(shd Shader) ShaderInfo {
|
||||
return C.sg_query_shader_info(shd)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_pipeline_info(pip Pipeline) PipelineInfo {
|
||||
return C.sg_query_pipeline_info(pip)
|
||||
}
|
||||
|
||||
// query_attachments_info returns runtime information about the `atts` / `Attachments`.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn query_attachments_info(atts Attachments) AttachmentsInfo {
|
||||
return C.sg_query_attachments_info(atts)
|
||||
}
|
||||
|
||||
// get resource creation desc struct with their default values replaced
|
||||
@[inline]
|
||||
pub fn query_buffer_defaults(desc &Buffer) BufferDesc {
|
||||
return C.sg_query_buffer_defaults(unsafe { &BufferDesc(voidptr(desc)) })
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_image_defaults(desc &Image) ImageDesc {
|
||||
return C.sg_query_image_defaults(unsafe { &ImageDesc(voidptr(desc)) })
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_shader_defaults(desc &Shader) ShaderDesc {
|
||||
return C.sg_query_shader_defaults(unsafe { &ShaderDesc(voidptr(desc)) })
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn query_pipeline_defaults(desc &Pipeline) PipelineDesc {
|
||||
return C.sg_query_pipeline_defaults(unsafe { &PipelineDesc(voidptr(desc)) })
|
||||
}
|
||||
|
||||
// query_attachments_defaults returns `AttachmentsDesc` with default values replaced.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
@[inline]
|
||||
pub fn query_attachments_defaults(desc &AttachmentsDesc) AttachmentsDesc {
|
||||
return C.sg_query_attachments_defaults(unsafe { &AttachmentsDesc(voidptr(desc)) })
|
||||
}
|
||||
|
||||
// frame stats
|
||||
|
||||
// enable_frame_stats enables the sokol frame statistics.
|
||||
@[inline]
|
||||
pub fn enable_frame_stats() {
|
||||
C.sg_enable_frame_stats()
|
||||
}
|
||||
|
||||
// disable_frame_stats disables the sokol frame statistics.
|
||||
@[inline]
|
||||
pub fn disable_frame_stats() {
|
||||
C.sg_disable_frame_stats()
|
||||
}
|
||||
|
||||
// frame_stats_enabled returns `true` if the sokol frame statistics is enabled.
|
||||
@[inline]
|
||||
pub fn frame_stats_enabled() bool {
|
||||
return C.sg_frame_stats_enabled()
|
||||
}
|
||||
|
||||
// query_frame_stats returns the sokol frame statistics for the current frame.
|
||||
@[inline]
|
||||
pub fn query_frame_stats() FrameStats {
|
||||
return C.sg_query_frame_stats()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
module gfx
|
||||
|
||||
import sokol.memory
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_allocator {
|
||||
pub mut:
|
||||
alloc_fn memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free_fn memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_logger {
|
||||
pub mut:
|
||||
func memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
module gfx
|
||||
|
||||
// setup and misc functions
|
||||
fn C.sg_setup(const_desc &C.sg_desc)
|
||||
fn C.sg_shutdown()
|
||||
fn C.sg_isvalid() bool
|
||||
fn C.sg_reset_state_cache()
|
||||
fn C.sg_install_trace_hooks(const_trace_hooks &C.sg_trace_hooks) C.sg_trace_hooks
|
||||
fn C.sg_push_debug_group(const_name &char)
|
||||
fn C.sg_pop_debug_group()
|
||||
fn C.sg_add_commit_listener(listener C.sg_commit_listener) bool
|
||||
fn C.sg_remove_commit_listener(listener C.sg_commit_listener) bool
|
||||
|
||||
// resource creation, destruction and updating
|
||||
fn C.sg_make_buffer(const_desc &C.sg_buffer_desc) C.sg_buffer
|
||||
fn C.sg_make_image(const_desc &C.sg_image_desc) C.sg_image
|
||||
fn C.sg_make_sampler(const_desc &C.sg_sampler_desc) C.sg_sampler
|
||||
fn C.sg_make_shader(const_desc &C.sg_shader_desc) C.sg_shader
|
||||
fn C.sg_make_pipeline(const_desc &C.sg_pipeline_desc) C.sg_pipeline
|
||||
fn C.sg_make_attachments(const_desc &C.sg_attachments_desc) C.sg_attachments
|
||||
fn C.sg_destroy_buffer(buf C.sg_buffer)
|
||||
fn C.sg_destroy_image(img C.sg_image)
|
||||
fn C.sg_destroy_sampler(smp C.sg_sampler)
|
||||
fn C.sg_destroy_shader(shd C.sg_shader)
|
||||
fn C.sg_destroy_pipeline(pip C.sg_pipeline)
|
||||
fn C.sg_destroy_attachments(atts C.sg_attachments)
|
||||
fn C.sg_update_buffer(buf C.sg_buffer, data &C.sg_range)
|
||||
fn C.sg_update_image(img C.sg_image, data &C.sg_image_data)
|
||||
fn C.sg_append_buffer(buf C.sg_buffer, data &C.sg_range) i32
|
||||
fn C.sg_query_buffer_overflow(buf C.sg_buffer) bool
|
||||
fn C.sg_query_buffer_will_overflow(buf C.sg_buffer, size usize) bool
|
||||
|
||||
// rendering functions
|
||||
fn C.sg_begin_pass(const_pass &C.sg_pass)
|
||||
fn C.sg_apply_viewport(x i32, y i32, width i32, height i32, origin_top_left bool)
|
||||
fn C.sg_apply_viewportf(x f32, y f32, width f32, height f32, origin_top_left bool)
|
||||
fn C.sg_apply_scissor_rect(x i32, y i32, width i32, height i32, origin_top_left bool)
|
||||
fn C.sg_apply_scissor_rectf(x f32, y f32, width f32, height f32, origin_top_left bool)
|
||||
fn C.sg_apply_pipeline(pip C.sg_pipeline)
|
||||
fn C.sg_apply_bindings(bindings &C.sg_bindings)
|
||||
fn C.sg_apply_uniforms(stage ShaderStage, ub_index i32, const_data &C.sg_range)
|
||||
fn C.sg_draw(base_element i32, num_elements i32, num_instances i32)
|
||||
fn C.sg_end_pass()
|
||||
fn C.sg_commit()
|
||||
|
||||
// getting information
|
||||
fn C.sg_query_desc() C.sg_desc
|
||||
fn C.sg_query_backend() Backend
|
||||
fn C.sg_query_features() C.sg_features
|
||||
fn C.sg_query_limits() C.sg_limits
|
||||
fn C.sg_query_pixelformat(fmt PixelFormat) C.sg_pixelformat_info
|
||||
|
||||
// get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)
|
||||
fn C.sg_query_buffer_state(buf C.sg_buffer) ResourceState
|
||||
fn C.sg_query_image_state(img C.sg_image) ResourceState
|
||||
fn C.sg_query_sampler_state(smp C.sg_sampler) ResourceState
|
||||
fn C.sg_query_shader_state(shd C.sg_shader) ResourceState
|
||||
fn C.sg_query_pipeline_state(pip C.sg_pipeline) ResourceState
|
||||
fn C.sg_query_attachments_state(atts C.sg_attachments) ResourceState
|
||||
|
||||
// get runtime information about a resource
|
||||
fn C.sg_query_buffer_info(buf C.sg_buffer) C.sg_buffer_info
|
||||
fn C.sg_query_image_info(img C.sg_image) C.sg_image_info
|
||||
fn C.sg_query_sampler_info(smp C.sg_sampler) C.sg_sampler_info
|
||||
fn C.sg_query_shader_info(shd C.sg_shader) C.sg_shader_info
|
||||
fn C.sg_query_pipeline_info(pip C.sg_pipeline) C.sg_pipeline_info
|
||||
fn C.sg_query_attachments_info(atts C.sg_attachments) C.sg_attachments_info
|
||||
|
||||
// get desc structs matching a specific resource (NOTE that not all creation attributes may be provided)
|
||||
fn C.sg_query_buffer_desc(buf C.sg_buffer) C.sg_buffer_desc
|
||||
fn C.sg_query_image_desc(img C.sg_image) C.sg_image_desc
|
||||
fn C.sg_query_sampler_desc(smp C.sg_sampler) C.sg_sampler_desc
|
||||
fn C.sg_query_shader_desc(shd C.sg_shader) C.sg_shader_desc
|
||||
fn C.sg_query_pipeline_desc(pip C.sg_pipeline) C.sg_pipeline_desc
|
||||
fn C.sg_query_attachments_desc(atts C.sg_attachments) C.sg_attachments_desc
|
||||
|
||||
// get resource creation desc struct with their default values replaced
|
||||
fn C.sg_query_buffer_defaults(const_desc &C.sg_buffer_desc) C.sg_buffer_desc
|
||||
fn C.sg_query_image_defaults(const_desc &C.sg_image_desc) C.sg_image_desc
|
||||
fn C.sg_query_sampler_defaults(const_desc &C.sg_sampler_desc) C.sg_sampler_desc
|
||||
fn C.sg_query_shader_defaults(const_desc &C.sg_shader_desc) C.sg_shader_desc
|
||||
fn C.sg_query_pipeline_defaults(const_desc &C.sg_pipeline_desc) C.sg_pipeline_desc
|
||||
fn C.sg_query_attachments_defaults(const_desc &C.sg_attachments_desc) C.sg_attachments_desc
|
||||
|
||||
// separate resource allocation and initialization (for async setup)
|
||||
fn C.sg_alloc_buffer() C.sg_buffer
|
||||
fn C.sg_alloc_image() C.sg_image
|
||||
fn C.sg_alloc_sampler() C.sg_sampler
|
||||
fn C.sg_alloc_shader() C.sg_shader
|
||||
fn C.sg_alloc_pipeline() C.sg_pipeline
|
||||
fn C.sg_alloc_attachments() C.sg_attachments
|
||||
fn C.sg_dealloc_buffer(buf C.sg_buffer)
|
||||
fn C.sg_dealloc_image(img C.sg_image)
|
||||
fn C.sg_dealloc_sampler(smp C.sg_sampler)
|
||||
fn C.sg_dealloc_shader(shd C.sg_shader)
|
||||
fn C.sg_dealloc_pipeline(pip C.sg_pipeline)
|
||||
fn C.sg_dealloc_attachments(atts C.sg_attachments)
|
||||
fn C.sg_init_buffer(buf C.sg_buffer, const_desc &C.sg_buffer_desc)
|
||||
fn C.sg_init_image(img C.sg_image, const_desc &C.sg_buffer_desc)
|
||||
fn C.sg_init_sampler(smg C.sg_sampler, const_desc &C.sg_sampler_desc)
|
||||
fn C.sg_init_shader(shd C.sg_shader, const_desc &C.sg_shader_desc)
|
||||
fn C.sg_init_pipeline(pip C.sg_pipeline, const_desc &C.sg_pipeline_desc)
|
||||
fn C.sg_init_attachments(atts C.sg_attachments, const_desc &C.sg_attachments_desc)
|
||||
fn C.sg_uninit_buffer(buf C.sg_buffer)
|
||||
fn C.sg_uninit_image(img C.sg_image)
|
||||
fn C.sg_uninit_sampler(smp C.sg_sampler)
|
||||
fn C.sg_uninit_shader(shd C.sg_shader)
|
||||
fn C.sg_uninit_pipeline(pip C.sg_pipeline)
|
||||
fn C.sg_uninit_attachments(atts C.sg_attachments)
|
||||
fn C.sg_fail_buffer(buf C.sg_buffer)
|
||||
fn C.sg_fail_image(img C.sg_image)
|
||||
fn C.sg_fail_sampler(smp C.sg_sampler)
|
||||
fn C.sg_fail_shader(shd C.sg_shader)
|
||||
fn C.sg_fail_pipeline(pip C.sg_pipeline)
|
||||
fn C.sg_fail_attachments(atts C.sg_attachments)
|
||||
|
||||
// frame stats
|
||||
fn C.sg_enable_frame_stats()
|
||||
fn C.sg_disable_frame_stats()
|
||||
fn C.sg_frame_stats_enabled() bool
|
||||
fn C.sg_query_frame_stats() C.sg_frame_stats
|
||||
@@ -0,0 +1,983 @@
|
||||
module gfx
|
||||
|
||||
// C.sg_desc describes
|
||||
pub struct C.sg_desc {
|
||||
pub mut:
|
||||
_start_canary u32
|
||||
buffer_pool_size int
|
||||
image_pool_size int
|
||||
sampler_pool_size int
|
||||
shader_pool_size int
|
||||
pipeline_pool_size int
|
||||
attachments_pool_size int
|
||||
uniform_buffer_size int
|
||||
max_commit_listeners int
|
||||
disable_validation bool // disable validation layer even in debug mode, useful for tests
|
||||
mtl_force_managed_storage_mode bool // for debugging: use Metal managed storage mode for resources even with UMA
|
||||
mtl_use_command_buffer_with_retained_references bool // Metal: use a managed MTLCommandBuffer which ref-counts used resources
|
||||
wgpu_disable_bindgroups_cache bool // set to true to disable the WebGPU backend BindGroup cache
|
||||
wgpu_bindgroups_cache_size int // number of slots in the WebGPU bindgroup cache (must be 2^N)
|
||||
allocator C.sg_allocator
|
||||
logger C.sg_logger // optional log function override
|
||||
environment C.sg_environment
|
||||
_end_canary u32
|
||||
}
|
||||
|
||||
pub type Desc = C.sg_desc
|
||||
|
||||
pub struct C.sg_color_target_state {
|
||||
pub mut:
|
||||
pixel_format PixelFormat
|
||||
write_mask ColorMask
|
||||
blend BlendState
|
||||
}
|
||||
|
||||
pub type ColorTargetState = C.sg_color_target_state
|
||||
|
||||
pub struct C.sg_pipeline_desc {
|
||||
pub mut:
|
||||
shader Shader
|
||||
layout VertexLayoutState
|
||||
depth DepthState
|
||||
stencil StencilState
|
||||
color_count int
|
||||
colors [4]ColorTargetState // C.SG_MAX_COLOR_ATTACHMENTS
|
||||
primitive_type PrimitiveType
|
||||
index_type IndexType
|
||||
cull_mode CullMode
|
||||
face_winding FaceWinding
|
||||
sample_count int
|
||||
blend_color Color
|
||||
alpha_to_coverage_enabled bool
|
||||
label &char = &char(unsafe { nil })
|
||||
}
|
||||
|
||||
pub type PipelineDesc = C.sg_pipeline_desc
|
||||
|
||||
pub struct C.sg_pipeline_info {
|
||||
pub:
|
||||
slot SlotInfo
|
||||
}
|
||||
|
||||
pub type PipelineInfo = C.sg_pipeline_info
|
||||
|
||||
pub struct C.sg_pipeline {
|
||||
pub:
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Pipeline = C.sg_pipeline
|
||||
|
||||
pub fn (mut p C.sg_pipeline) free() {
|
||||
C.sg_destroy_pipeline(*p)
|
||||
}
|
||||
|
||||
pub struct C.sg_attachments {
|
||||
id u32
|
||||
}
|
||||
|
||||
// Attachments represents data that can be attached to a render pass.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
pub type Attachments = C.sg_attachments
|
||||
|
||||
// free frees the resources occupied by the struct
|
||||
pub fn (mut a C.sg_attachments) free() {
|
||||
C.sg_destroy_attachments(*a)
|
||||
}
|
||||
|
||||
pub struct C.sg_attachment_desc {
|
||||
pub mut:
|
||||
image Image
|
||||
mip_level int
|
||||
slice int
|
||||
}
|
||||
|
||||
pub type AttachmentDesc = C.sg_attachment_desc
|
||||
|
||||
pub struct C.sg_attachments_desc {
|
||||
pub mut:
|
||||
_start_canary u32
|
||||
colors [4]AttachmentDesc
|
||||
resolves [4]AttachmentDesc
|
||||
depth_stencil AttachmentDesc
|
||||
label &char = unsafe { nil }
|
||||
_end_canary u32
|
||||
}
|
||||
|
||||
pub type AttachmentsDesc = C.sg_attachments_desc
|
||||
|
||||
pub struct C.sg_attachments_info {
|
||||
pub mut:
|
||||
slot SlotInfo // resource pool slot info
|
||||
}
|
||||
|
||||
pub type AttachmentsInfo = C.sg_attachments_info
|
||||
|
||||
pub struct C.sg_bindings {
|
||||
pub mut:
|
||||
_start_canary u32
|
||||
vertex_buffers [8]Buffer
|
||||
vertex_buffer_offsets [8]int
|
||||
index_buffer Buffer
|
||||
index_buffer_offset int
|
||||
vs StageBindings
|
||||
fs StageBindings
|
||||
_end_canary u32
|
||||
// vs_images [8]Image // old
|
||||
// fs_images [8]Image // old
|
||||
}
|
||||
|
||||
pub type Bindings = C.sg_bindings
|
||||
|
||||
pub fn (mut b Bindings) set_vert_image(index int, img Image) {
|
||||
b.vs.images[index] = img
|
||||
}
|
||||
|
||||
pub fn (mut b Bindings) set_frag_image(index int, img Image) {
|
||||
b.fs.images[index] = img
|
||||
}
|
||||
|
||||
pub fn (b &Bindings) update_vert_buffer(index int, data voidptr, element_size int, element_count int) {
|
||||
range := Range{
|
||||
ptr: data
|
||||
size: usize(element_size * element_count)
|
||||
}
|
||||
C.sg_update_buffer(b.vertex_buffers[index], &range)
|
||||
}
|
||||
|
||||
pub fn (b &Bindings) append_vert_buffer(index int, data voidptr, element_size int, element_count int) int {
|
||||
range := Range{
|
||||
ptr: data
|
||||
size: usize(element_size * element_count)
|
||||
}
|
||||
return C.sg_append_buffer(b.vertex_buffers[index], &range)
|
||||
}
|
||||
|
||||
pub fn (b &Bindings) update_index_buffer(data voidptr, element_size int, element_count int) {
|
||||
range := Range{
|
||||
ptr: data
|
||||
size: usize(element_size * element_count)
|
||||
}
|
||||
C.sg_update_buffer(b.index_buffer, &range)
|
||||
}
|
||||
|
||||
pub fn (b &Bindings) append_index_buffer(data voidptr, element_size int, element_count int) int {
|
||||
range := Range{
|
||||
ptr: data
|
||||
size: usize(element_size * element_count)
|
||||
}
|
||||
return C.sg_append_buffer(b.index_buffer, &range)
|
||||
}
|
||||
|
||||
pub struct C.sg_stage_bindings {
|
||||
pub mut:
|
||||
images [12]Image
|
||||
samplers [8]Sampler
|
||||
storage_buffers [8]Buffer
|
||||
}
|
||||
|
||||
pub type StageBindings = C.sg_stage_bindings
|
||||
|
||||
@[heap]
|
||||
pub struct C.sg_shader_desc {
|
||||
pub mut:
|
||||
attrs [16]ShaderAttrDesc
|
||||
vs ShaderStageDesc
|
||||
fs ShaderStageDesc
|
||||
label &char
|
||||
}
|
||||
|
||||
pub type ShaderDesc = C.sg_shader_desc
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_vert_src(src string) &ShaderDesc {
|
||||
desc.vs.source = &char(src.str)
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_frag_src(src string) &ShaderDesc {
|
||||
desc.fs.source = &char(src.str)
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_vert_image(index int, name string) &ShaderDesc {
|
||||
// desc.vs.images[index].name = &char(name.str)
|
||||
desc.vs.images[index].image_type = ._2d
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_frag_image(index int, name string) &ShaderDesc {
|
||||
// desc.fs.images[index].name = &char(name.str)
|
||||
desc.fs.images[index].image_type = ._2d
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_vert_uniform_block_size(block_index int, size usize) &ShaderDesc {
|
||||
desc.vs.uniform_blocks[block_index].size = size
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_frag_uniform_block_size(block_index int, size usize) &ShaderDesc {
|
||||
desc.fs.uniform_blocks[block_index].size = size
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_vert_uniform(block_index int, uniform_index int, name string, typ UniformType,
|
||||
array_count int) &ShaderDesc {
|
||||
desc.vs.uniform_blocks[block_index].uniforms[uniform_index].name = &char(name.str)
|
||||
desc.vs.uniform_blocks[block_index].uniforms[uniform_index].type = typ
|
||||
desc.vs.uniform_blocks[block_index].uniforms[uniform_index].array_count = array_count
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (mut desc C.sg_shader_desc) set_frag_uniform(block_index int, uniform_index int, name string, typ UniformType,
|
||||
array_count int) &ShaderDesc {
|
||||
desc.fs.uniform_blocks[block_index].uniforms[uniform_index].name = &char(name.str)
|
||||
desc.fs.uniform_blocks[block_index].uniforms[uniform_index].type = typ
|
||||
desc.fs.uniform_blocks[block_index].uniforms[uniform_index].array_count = array_count
|
||||
return desc
|
||||
}
|
||||
|
||||
pub fn (desc &ShaderDesc) make_shader() Shader {
|
||||
return C.sg_make_shader(desc)
|
||||
}
|
||||
|
||||
pub struct C.sg_shader_attr_desc {
|
||||
pub mut:
|
||||
name &char // GLSL vertex attribute name (only required for GLES2)
|
||||
sem_name &char // HLSL semantic name
|
||||
sem_index int // HLSL semantic index
|
||||
}
|
||||
|
||||
pub type ShaderAttrDesc = C.sg_shader_attr_desc
|
||||
|
||||
pub struct C.sg_shader_stage_desc {
|
||||
pub mut:
|
||||
source &char
|
||||
bytecode Range
|
||||
entry &char
|
||||
d3d11_target &char
|
||||
uniform_blocks [4]ShaderUniformBlockDesc
|
||||
storage_buffers [8]ShaderStorageBufferDesc
|
||||
images [12]ShaderImageDesc
|
||||
samplers [8]ShaderSamplerDesc
|
||||
image_sampler_pairs [12]ShaderImageSamplerPairDesc
|
||||
}
|
||||
|
||||
pub type ShaderStageDesc = C.sg_shader_stage_desc
|
||||
|
||||
pub fn (mut desc ShaderStageDesc) set_image(index int, name string) ShaderStageDesc {
|
||||
// desc.images[index].name = &char(name.str)
|
||||
desc.images[index].image_type = ._2d
|
||||
return *desc
|
||||
}
|
||||
|
||||
pub struct C.sg_shader_uniform_block_desc {
|
||||
pub mut:
|
||||
size usize
|
||||
layout UniformLayout
|
||||
uniforms [16]ShaderUniformDesc
|
||||
}
|
||||
|
||||
pub type ShaderUniformBlockDesc = C.sg_shader_uniform_block_desc
|
||||
|
||||
pub struct C.sg_shader_uniform_desc {
|
||||
pub mut:
|
||||
name &char
|
||||
type UniformType
|
||||
array_count int
|
||||
}
|
||||
|
||||
pub type ShaderUniformDesc = C.sg_shader_uniform_desc
|
||||
|
||||
pub struct C.sg_shader_image_desc {
|
||||
pub mut:
|
||||
used bool
|
||||
multisampled bool
|
||||
// name &char
|
||||
image_type ImageType
|
||||
sample_type ImageSampleType
|
||||
}
|
||||
|
||||
pub type ShaderImageDesc = C.sg_shader_image_desc
|
||||
|
||||
pub struct C.sg_shader_storage_buffer_desc {
|
||||
pub mut:
|
||||
used bool
|
||||
readonly bool
|
||||
}
|
||||
|
||||
pub type ShaderStorageBufferDesc = C.sg_shader_storage_buffer_desc
|
||||
|
||||
pub struct C.sg_shader_sampler_desc {
|
||||
pub mut:
|
||||
used bool
|
||||
sampler_type SamplerType
|
||||
}
|
||||
|
||||
pub type ShaderSamplerDesc = C.sg_shader_sampler_desc
|
||||
|
||||
pub struct C.sg_shader_image_sampler_pair_desc {
|
||||
pub mut:
|
||||
used bool
|
||||
image_slot int
|
||||
sampler_slot int
|
||||
glsl_name &char
|
||||
}
|
||||
|
||||
pub type ShaderImageSamplerPairDesc = C.sg_shader_image_sampler_pair_desc
|
||||
|
||||
pub struct C.sg_shader_info {
|
||||
pub:
|
||||
slot SlotInfo
|
||||
}
|
||||
|
||||
pub type ShaderInfo = C.sg_shader_info
|
||||
|
||||
pub struct C.sg_range {
|
||||
pub mut:
|
||||
ptr voidptr
|
||||
size usize
|
||||
}
|
||||
|
||||
pub type Range = C.sg_range
|
||||
|
||||
pub struct C.sg_color {
|
||||
pub mut:
|
||||
r f32
|
||||
g f32
|
||||
b f32
|
||||
a f32
|
||||
}
|
||||
|
||||
pub type Color = C.sg_color
|
||||
|
||||
pub struct C.sg_shader {
|
||||
pub:
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Shader = C.sg_shader
|
||||
|
||||
pub fn (mut s Shader) free() {
|
||||
C.sg_destroy_shader(*s)
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_gl {
|
||||
num_bind_buffer u32
|
||||
num_active_texture u32
|
||||
num_bind_texture u32
|
||||
num_bind_sampler u32
|
||||
num_use_program u32
|
||||
num_render_state u32
|
||||
num_vertex_attrib_pointer u32
|
||||
num_vertex_attrib_divisor u32
|
||||
num_enable_vertex_attrib_array u32
|
||||
num_disable_vertex_attrib_array u32
|
||||
num_uniform u32
|
||||
}
|
||||
|
||||
pub type FrameStatsGL = C.sg_frame_stats_gl
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11_pass {
|
||||
num_om_set_render_targets u32
|
||||
num_clear_render_target_view u32
|
||||
num_clear_depth_stencil_view u32
|
||||
num_resolve_subresource u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11Pass = C.sg_frame_stats_d3d11_pass
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11_pipeline {
|
||||
num_rs_set_state u32
|
||||
num_om_set_depth_stencil_state u32
|
||||
num_om_set_blend_state u32
|
||||
num_ia_set_primitive_topology u32
|
||||
num_ia_set_input_layout u32
|
||||
num_vs_set_shader u32
|
||||
num_vs_set_constant_buffers u32
|
||||
num_ps_set_shader u32
|
||||
num_ps_set_constant_buffers u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11Pipeline = C.sg_frame_stats_d3d11_pipeline
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11_bindings {
|
||||
num_ia_set_vertex_buffers u32
|
||||
num_ia_set_index_buffer u32
|
||||
num_vs_set_shader_resources u32
|
||||
num_ps_set_shader_resources u32
|
||||
num_vs_set_samplers u32
|
||||
num_ps_set_samplers u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11Bindings = C.sg_frame_stats_d3d11_bindings
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11_uniforms {
|
||||
num_update_subresource u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11Uniforms = C.sg_frame_stats_d3d11_uniforms
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11_draw {
|
||||
num_draw_indexed_instanced u32
|
||||
num_draw_indexed u32
|
||||
num_draw_instanced u32
|
||||
num_draw u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11Draw = C.sg_frame_stats_d3d11_draw
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_d3d11 {
|
||||
pass FrameStatsD3D11Pass
|
||||
pipeline FrameStatsD3D11Pipeline
|
||||
bindings FrameStatsD3D11Bindings
|
||||
uniforms FrameStatsD3D11Uniforms
|
||||
draw FrameStatsD3D11Draw
|
||||
num_map u32
|
||||
num_unmap u32
|
||||
}
|
||||
|
||||
pub type FrameStatsD3D11 = C.sg_frame_stats_d3d11
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_metal_idpool {
|
||||
num_added u32
|
||||
num_released u32
|
||||
num_garbage_collected u32
|
||||
}
|
||||
|
||||
pub type FrameStatsMetalIdpool = C.sg_frame_stats_metal_idpool
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_metal_pipeline {
|
||||
num_set_blend_color u32
|
||||
num_set_cull_mode u32
|
||||
num_set_front_facing_winding u32
|
||||
num_set_stencil_reference_value u32
|
||||
num_set_depth_bias u32
|
||||
num_set_render_pipeline_state u32
|
||||
num_set_depth_stencil_state u32
|
||||
}
|
||||
|
||||
pub type FrameStatsMetalPipeline = C.sg_frame_stats_metal_pipeline
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_metal_bindings {
|
||||
num_set_vertex_buffer u32
|
||||
num_set_vertex_texture u32
|
||||
num_set_vertex_sampler_state u32
|
||||
num_set_fragment_buffer u32
|
||||
num_set_fragment_texture u32
|
||||
num_set_fragment_sampler_state u32
|
||||
}
|
||||
|
||||
pub type FrameStatsMetalBindings = C.sg_frame_stats_metal_bindings
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_metal_uniforms {
|
||||
num_set_vertex_buffer_offset u32
|
||||
num_set_fragment_buffer_offset u32
|
||||
}
|
||||
|
||||
pub type FrameStatsMetalUniforms = C.sg_frame_stats_metal_uniforms
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_metal {
|
||||
idpool FrameStatsMetalIdpool
|
||||
pipeline FrameStatsMetalPipeline
|
||||
bindings FrameStatsMetalBindings
|
||||
uniforms FrameStatsMetalUniforms
|
||||
}
|
||||
|
||||
pub type FrameStatsMetal = C.sg_frame_stats_metal
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_wgpu_uniforms {
|
||||
num_set_bindgroup u32
|
||||
size_write_buffer u32
|
||||
}
|
||||
|
||||
pub type FrameStatsWGPUUniforms = C.sg_frame_stats_wgpu_uniforms
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_wgpu_bindings {
|
||||
num_set_vertex_buffer u32
|
||||
num_skip_redundant_vertex_buffer u32
|
||||
num_set_index_buffer u32
|
||||
num_skip_redundant_index_buffer u32
|
||||
num_create_bindgroup u32
|
||||
num_discard_bindgroup u32
|
||||
num_set_bindgroup u32
|
||||
num_skip_redundant_bindgroup u32
|
||||
num_bindgroup_cache_hits u32
|
||||
num_bindgroup_cache_misses u32
|
||||
num_bindgroup_cache_collisions u32
|
||||
num_bindgroup_cache_hash_vs_key_mismatch u32
|
||||
}
|
||||
|
||||
pub type FrameStatsWGPUBindings = C.sg_frame_stats_wgpu_bindings
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats_wgpu {
|
||||
uniforms FrameStatsWGPUUniforms
|
||||
bindings FrameStatsWGPUBindings
|
||||
}
|
||||
|
||||
pub type FrameStatsWGPU = C.sg_frame_stats_wgpu
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_frame_stats {
|
||||
frame_index u32 // current frame counter, starts at 0
|
||||
|
||||
num_passes u32
|
||||
num_apply_viewport u32
|
||||
num_apply_scissor_rect u32
|
||||
num_apply_pipeline u32
|
||||
num_apply_bindings u32
|
||||
num_apply_uniforms u32
|
||||
num_draw u32
|
||||
num_update_buffer u32
|
||||
num_append_buffer u32
|
||||
num_update_image u32
|
||||
|
||||
size_apply_uniforms u32
|
||||
size_update_buffer u32
|
||||
size_append_buffer u32
|
||||
size_update_image u32
|
||||
|
||||
gl FrameStatsGL
|
||||
d3d11 FrameStatsD3D11
|
||||
metal FrameStatsMetal
|
||||
wgpu FrameStatsWGPU
|
||||
}
|
||||
|
||||
pub type FrameStats = C.sg_frame_stats
|
||||
|
||||
pub struct C.sg_pass_action {
|
||||
pub mut:
|
||||
colors [4]ColorAttachmentAction
|
||||
depth DepthAttachmentAction
|
||||
stencil StencilAttachmentAction
|
||||
}
|
||||
|
||||
pub type PassAction = C.sg_pass_action
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_metal_swapchain {
|
||||
pub mut:
|
||||
current_drawable voidptr
|
||||
depth_stencil_texture voidptr // MTLTexture
|
||||
msaa_color_texture voidptr // MTLTexture
|
||||
}
|
||||
|
||||
pub type MetalSwapchain = C.sg_metal_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_d3d11_swapchain {
|
||||
pub mut:
|
||||
render_view voidptr // ID3D11RenderTargetView
|
||||
resolve_view voidptr // ID3D11RenderTargetView
|
||||
depth_stencil_view voidptr // ID3D11DepthStencilView
|
||||
}
|
||||
|
||||
pub type D3d11Swapchain = C.sg_d3d11_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_wgpu_swapchain {
|
||||
pub mut:
|
||||
render_view voidptr // WGPUTextureView
|
||||
resolve_view voidptr // WGPUTextureView
|
||||
depth_stencil_view voidptr // WGPUTextureView
|
||||
}
|
||||
|
||||
pub type WgpuSwapchain = C.sg_wgpu_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_gl_swapchain {
|
||||
pub mut:
|
||||
framebuffer u32
|
||||
}
|
||||
|
||||
pub type GlSwapchain = C.sg_gl_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_swapchain {
|
||||
pub mut:
|
||||
width int
|
||||
height int
|
||||
sample_count int
|
||||
color_format PixelFormat
|
||||
depth_format PixelFormat
|
||||
metal MetalSwapchain
|
||||
d3d11 D3d11Swapchain
|
||||
wgpu WgpuSwapchain
|
||||
gl GlSwapchain
|
||||
}
|
||||
|
||||
pub type Swapchain = C.sg_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_pass {
|
||||
pub mut:
|
||||
_start_canary u32
|
||||
action PassAction
|
||||
attachments Attachments
|
||||
swapchain Swapchain
|
||||
label &char = unsafe { nil }
|
||||
_end_canary u32
|
||||
}
|
||||
|
||||
pub type Pass = C.sg_pass
|
||||
|
||||
pub struct C.sg_buffer_desc {
|
||||
pub mut:
|
||||
size usize
|
||||
type BufferType
|
||||
usage Usage
|
||||
data Range
|
||||
label &char
|
||||
// backend-specific resources
|
||||
gl_buffers [2]u32
|
||||
mtl_buffers [2]voidptr
|
||||
d3d11_buffer voidptr
|
||||
wgpu_buffer voidptr
|
||||
}
|
||||
|
||||
pub type BufferDesc = C.sg_buffer_desc
|
||||
|
||||
pub struct C.sg_slot_info {
|
||||
state ResourceState
|
||||
res_id u32
|
||||
ctx_id u32
|
||||
}
|
||||
|
||||
pub type SlotInfo = C.sg_slot_info
|
||||
|
||||
pub struct C.sg_buffer_info {
|
||||
pub:
|
||||
slot SlotInfo
|
||||
update_frame_index u32
|
||||
append_frame_index u32
|
||||
append_pos int
|
||||
append_overflow bool
|
||||
num_slots int
|
||||
active_slot int
|
||||
}
|
||||
|
||||
pub type BufferInfo = C.sg_buffer_info
|
||||
|
||||
pub struct C.sg_buffer {
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Buffer = C.sg_buffer
|
||||
|
||||
pub fn (mut b Buffer) free() {
|
||||
C.sg_destroy_buffer(*b)
|
||||
}
|
||||
|
||||
pub struct C.sg_image_desc {
|
||||
pub mut:
|
||||
type ImageType
|
||||
render_target bool
|
||||
width int
|
||||
height int
|
||||
num_slices int
|
||||
num_mipmaps int
|
||||
usage Usage
|
||||
pixel_format PixelFormat
|
||||
sample_count int
|
||||
// min_filter Filter
|
||||
// mag_filter Filter
|
||||
// wrap_u Wrap
|
||||
// wrap_v Wrap
|
||||
// wrap_w Wrap
|
||||
// border_color BorderColor
|
||||
// max_anisotropy u32
|
||||
// min_lod f32
|
||||
// max_lod f32
|
||||
data ImageData
|
||||
label &char
|
||||
// backend-specific resources
|
||||
gl_textures [2]u32
|
||||
gl_texture_target u32
|
||||
mtl_textures [2]voidptr
|
||||
d3d11_texture voidptr
|
||||
d3d11_shader_resource_view voidptr
|
||||
wgpu_texture voidptr
|
||||
}
|
||||
|
||||
pub type ImageDesc = C.sg_image_desc
|
||||
|
||||
pub struct C.sg_sampler_desc {
|
||||
min_filter Filter
|
||||
mag_filter Filter
|
||||
mipmap_filter Filter
|
||||
wrap_u Wrap
|
||||
wrap_v Wrap
|
||||
wrap_w Wrap
|
||||
min_lod f32
|
||||
max_lod f32
|
||||
border_color BorderColor
|
||||
compare CompareFunc
|
||||
max_anisotropy u32
|
||||
label &char
|
||||
// backend-specific resources
|
||||
gl_sampler u32
|
||||
mtl_sampler voidptr
|
||||
d3d11_sampler voidptr
|
||||
wgpu_sampler voidptr
|
||||
}
|
||||
|
||||
pub type SamplerDesc = C.sg_sampler_desc
|
||||
|
||||
pub struct C.sg_image_info {
|
||||
pub mut:
|
||||
slot SlotInfo // resource pool slot info
|
||||
upd_frame_index u32 // frame index of last sg_update_image()
|
||||
num_slots int // number of renaming-slots for dynamically updated images
|
||||
active_slot int // currently active write-slot for dynamically updated images
|
||||
}
|
||||
|
||||
pub type ImageInfo = C.sg_image_info
|
||||
|
||||
pub struct C.sg_image {
|
||||
pub mut:
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Image = C.sg_image
|
||||
|
||||
pub fn (mut i Image) free() {
|
||||
C.sg_destroy_image(*i)
|
||||
}
|
||||
|
||||
pub struct C.sg_sampler {
|
||||
pub mut:
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Sampler = C.sg_sampler
|
||||
|
||||
pub const sg_cubeface_num = 6
|
||||
|
||||
pub const sg_max_mipmaps = 16
|
||||
|
||||
pub struct C.sg_image_data {
|
||||
pub mut:
|
||||
subimage [sg_cubeface_num][sg_max_mipmaps]Range
|
||||
}
|
||||
|
||||
pub type ImageData = C.sg_image_data
|
||||
|
||||
pub struct C.sg_features {
|
||||
pub:
|
||||
origin_top_left bool // framebuffer and texture origin is in top left corner
|
||||
image_clamp_to_border bool // border color and clamp-to-border UV-wrap mode is supported
|
||||
mrt_independent_blend_state bool // multiple-render-target rendering can use per-render-target blend state
|
||||
mrt_independent_write_mask bool // multiple-render-target rendering can use per-render-target color write masks
|
||||
storage_buffer bool // storage buffers are supported
|
||||
}
|
||||
|
||||
pub type Features = C.sg_features
|
||||
|
||||
pub struct C.sg_limits {
|
||||
pub:
|
||||
max_image_size_2d int // max width/height of SG_IMAGETYPE_2D images
|
||||
max_image_size_cube int // max width/height of SG_IMAGETYPE_CUBE images
|
||||
max_image_size_3d int // max width/height/depth of SG_IMAGETYPE_3D images
|
||||
max_image_size_array int // max width/height pf SG_IMAGETYPE_ARRAY images
|
||||
max_image_array_layers int // max number of layers in SG_IMAGETYPE_ARRAY images
|
||||
max_vertex_attrs int // <= SG_MAX_VERTEX_ATTRIBUTES (only on some GLES2 impls)
|
||||
gl_max_vertex_uniform_components int // <= GL_MAX_VERTEX_UNIFORM_COMPONENTS (only on GL backends)
|
||||
gl_max_combined_texture_image_units int // <= GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (only on GL backends)
|
||||
}
|
||||
|
||||
pub type Limits = C.sg_limits
|
||||
|
||||
pub struct C.sg_vertex_layout_state {
|
||||
pub mut:
|
||||
buffers [8]VertexBufferLayoutState
|
||||
attrs [16]VertexAttrDesc
|
||||
}
|
||||
|
||||
pub type VertexLayoutState = C.sg_vertex_layout_state
|
||||
|
||||
pub struct C.sg_vertex_buffer_layout_state {
|
||||
pub mut:
|
||||
stride int
|
||||
step_func VertexStep
|
||||
step_rate int
|
||||
}
|
||||
|
||||
pub type VertexBufferLayoutState = C.sg_vertex_buffer_layout_state
|
||||
|
||||
pub struct C.sg_vertex_attr_state {
|
||||
pub mut:
|
||||
buffer_index int
|
||||
offset int
|
||||
format VertexFormat
|
||||
}
|
||||
|
||||
pub type VertexAttrDesc = C.sg_vertex_attr_state
|
||||
|
||||
pub struct C.sg_stencil_state {
|
||||
enabled bool
|
||||
front StencilFaceState
|
||||
back StencilFaceState
|
||||
read_mask u8
|
||||
write_mask u8
|
||||
ref u8
|
||||
}
|
||||
|
||||
pub type StencilState = C.sg_stencil_state
|
||||
|
||||
pub struct C.sg_depth_state {
|
||||
pixel_format PixelFormat
|
||||
compare CompareFunc
|
||||
write_enabled bool
|
||||
bias f32
|
||||
bias_slope_scale f32
|
||||
bias_clamp f32
|
||||
}
|
||||
|
||||
pub type DepthState = C.sg_depth_state
|
||||
|
||||
pub struct C.sg_stencil_face_state {
|
||||
compare CompareFunc
|
||||
fail_op StencilOp
|
||||
depth_fail_op StencilOp
|
||||
pass_op StencilOp
|
||||
}
|
||||
|
||||
pub type StencilFaceState = C.sg_stencil_face_state
|
||||
|
||||
pub struct C.sg_blend_state {
|
||||
pub mut:
|
||||
enabled bool
|
||||
src_factor_rgb BlendFactor
|
||||
dst_factor_rgb BlendFactor
|
||||
op_rgb BlendOp
|
||||
src_factor_alpha BlendFactor
|
||||
dst_factor_alpha BlendFactor
|
||||
op_alpha BlendOp
|
||||
}
|
||||
|
||||
pub type BlendState = C.sg_blend_state
|
||||
|
||||
pub struct C.sg_color_attachment_action {
|
||||
pub mut:
|
||||
load_action LoadAction
|
||||
store_action StoreAction
|
||||
clear_value Color
|
||||
}
|
||||
|
||||
pub type ColorAttachmentAction = C.sg_color_attachment_action
|
||||
|
||||
/*
|
||||
pub fn (mut action C.sg_color_attachment_action) set_color_values(r, g, b, a f32) {
|
||||
action.val[0] = r
|
||||
action.val[1] = g
|
||||
action.val[2] = b
|
||||
action.val[3] = a
|
||||
}
|
||||
*/
|
||||
pub struct C.sg_depth_attachment_action {
|
||||
pub mut:
|
||||
load_action LoadAction
|
||||
store_action StoreAction
|
||||
clear_value f32
|
||||
}
|
||||
|
||||
pub type DepthAttachmentAction = C.sg_depth_attachment_action
|
||||
|
||||
pub struct C.sg_stencil_attachment_action {
|
||||
pub mut:
|
||||
load_action LoadAction
|
||||
store_action StoreAction
|
||||
clear_value u8
|
||||
}
|
||||
|
||||
pub type StencilAttachmentAction = C.sg_stencil_attachment_action
|
||||
|
||||
pub struct C.sg_pixelformat_info {
|
||||
pub:
|
||||
sample bool // pixel format can be sampled in shaders
|
||||
filter bool // pixel format can be sampled with filtering
|
||||
render bool // pixel format can be used as render target
|
||||
blend bool // alpha-blending is supported
|
||||
msaa bool // pixel format can be used as MSAA render target
|
||||
depth bool // pixel format is a depth format
|
||||
}
|
||||
|
||||
pub type PixelFormatInfo = C.sg_pixelformat_info
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_environment_defaults {
|
||||
pub mut:
|
||||
color_format PixelFormat
|
||||
depth_format PixelFormat
|
||||
sample_count int
|
||||
}
|
||||
|
||||
pub type EnvironmentDefaults = C.sg_environment_defaults
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_metal_environment {
|
||||
pub mut:
|
||||
device voidptr
|
||||
}
|
||||
|
||||
pub type MetalEnvironment = C.sg_metal_environment
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_d3d11_environment {
|
||||
pub mut:
|
||||
device voidptr
|
||||
device_context voidptr
|
||||
}
|
||||
|
||||
pub type D3d11Environment = C.sg_d3d11_environment
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_wgpu_environment {
|
||||
pub mut:
|
||||
device voidptr
|
||||
}
|
||||
|
||||
pub type WgpuEnvironment = C.sg_wgpu_environment
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sg_environment {
|
||||
pub mut:
|
||||
defaults EnvironmentDefaults
|
||||
metal MetalEnvironment
|
||||
d3d11 D3d11Environment
|
||||
wgpu WgpuEnvironment
|
||||
}
|
||||
|
||||
pub type Environment = C.sg_environment
|
||||
|
||||
// C.sg_commit_listener is used with sg_add_commit_listener, to add a callback,
|
||||
// which will be called in sg_commit(). This is useful for libraries building
|
||||
// on top of sokol-gfx to be notified about when a frame ends (instead of having
|
||||
// to guess, or add a manual 'new-frame' function).
|
||||
pub struct C.sg_commit_listener {
|
||||
pub:
|
||||
func fn (user_data voidptr)
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
pub type CommitListener = C.sg_commit_listener
|
||||
|
||||
pub struct C.sg_trace_hooks {}
|
||||
|
||||
// pub struct C.sg_resource_state {} enum
|
||||
pub struct C.sg_sampler_info {}
|
||||
@@ -0,0 +1,29 @@
|
||||
// vtest build: !msvc
|
||||
// vtest flaky: true
|
||||
// vtest retry: 1
|
||||
module gfx
|
||||
|
||||
import os
|
||||
|
||||
fn assert_program_panics(source string, expected string) {
|
||||
source_path := os.join_path(os.temp_dir(),
|
||||
'sokol_gfx_make_image_requires_setup_${os.getpid()}.v')
|
||||
os.write_file(source_path, source) or { panic(err) }
|
||||
defer {
|
||||
os.rm(source_path) or {}
|
||||
}
|
||||
res := os.execute('${os.quoted_path(@VEXE)} run ${os.quoted_path(source_path)}')
|
||||
assert res.exit_code != 0, 'expected the test program to fail'
|
||||
assert res.output.contains(expected), 'expected `${expected}` in `${res.output}`'
|
||||
}
|
||||
|
||||
fn test_make_image_requires_setup() {
|
||||
assert_program_panics('import sokol.gfx
|
||||
|
||||
fn main() {
|
||||
mut desc := gfx.ImageDesc{}
|
||||
_ = gfx.make_image(&desc)
|
||||
}
|
||||
',
|
||||
'sokol.gfx is not initialized; call gfx.setup(...) before gfx.make_image(...)')
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
module gfx
|
||||
|
||||
// create_clear_pass_action returns a *clearing* `PassAction` that clears the `Pass`
|
||||
// with the color defined by the color components `r`ed,`g`reen, `b`lue and `a`lpha.
|
||||
pub fn create_clear_pass_action(r f32, g f32, b f32, a f32) PassAction {
|
||||
mut color_action := ColorAttachmentAction{
|
||||
load_action: .clear
|
||||
clear_value: Color{
|
||||
r: r
|
||||
g: g
|
||||
b: b
|
||||
a: a
|
||||
}
|
||||
}
|
||||
// color_action.set_color_values(r, g, b, a)
|
||||
mut pass_action := PassAction{}
|
||||
pass_action.colors[0] = color_action
|
||||
return pass_action
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
module memory
|
||||
|
||||
pub type FnAllocatorAlloc = fn (size usize, user_data voidptr) voidptr
|
||||
|
||||
pub type FnAllocatorFree = fn (ptr voidptr, user_data voidptr)
|
||||
|
||||
pub type FnLogCb = fn (const_tag &char, log_level u32, log_item_id u32, const_message_or_null &char, line_nr u32, const_filename_or_null &char, user_data voidptr)
|
||||
|
||||
// salloc - used in the allocator structs, that the SOKOL libraries use, for allocating new memory blocks
|
||||
pub fn salloc(size usize, user_data voidptr) voidptr {
|
||||
res := unsafe { malloc(int(size)) }
|
||||
$if trace_sokol_memory ? {
|
||||
eprintln('sokol.memory.salloc | user_data: ${user_data:x} | size: ${size:10} | res: ${res:x}')
|
||||
}
|
||||
$if trace_sokol_memory_salloc_backtrace ? {
|
||||
print_backtrace()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// sfree - used in the allocator structs, that the SOKOL libraries use, for freeing memory
|
||||
pub fn sfree(ptr voidptr, user_data voidptr) {
|
||||
$if trace_sokol_memory ? {
|
||||
eprintln(' sokol.memory.sfree | user_data: ${user_data:x} | ptr: ${ptr:x}')
|
||||
}
|
||||
$if trace_sokol_memory_sfree_backtrace ? {
|
||||
print_backtrace()
|
||||
}
|
||||
unsafe { free(ptr) }
|
||||
}
|
||||
|
||||
fn C.SOKOL_LOG(const_message &char)
|
||||
|
||||
pub fn slog(const_tag &char, log_level u32, log_item_id u32, const_message_or_null &char, line_nr u32,
|
||||
const_filename_or_null &char, user_data voidptr) {
|
||||
C.fprintf(C.stderr,
|
||||
c'sokol.memory.slog | user_data: %p, const_tag: %s, level: %d, item_id: %d, fname: %s, line: %d, message: %s\n',
|
||||
user_data, const_tag, log_level, log_item_id, const_filename_or_null, line_nr,
|
||||
const_message_or_null)
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
module sapp
|
||||
|
||||
pub enum EventType {
|
||||
invalid
|
||||
key_down
|
||||
key_up
|
||||
char
|
||||
mouse_down
|
||||
mouse_up
|
||||
mouse_scroll
|
||||
mouse_move
|
||||
mouse_enter
|
||||
mouse_leave
|
||||
touches_began
|
||||
touches_moved
|
||||
touches_ended
|
||||
touches_cancelled
|
||||
resized
|
||||
iconified
|
||||
restored
|
||||
focused
|
||||
unfocused
|
||||
suspended
|
||||
resumed
|
||||
quit_requested
|
||||
clipboard_pasted
|
||||
files_dropped
|
||||
num
|
||||
}
|
||||
|
||||
pub enum MouseButton {
|
||||
invalid = -1
|
||||
left = 0
|
||||
right = 1
|
||||
middle = 2
|
||||
}
|
||||
|
||||
pub enum MouseCursor {
|
||||
default = C.SAPP_MOUSECURSOR_DEFAULT
|
||||
arrow = C.SAPP_MOUSECURSOR_ARROW
|
||||
ibeam = C.SAPP_MOUSECURSOR_IBEAM
|
||||
crosshair = C.SAPP_MOUSECURSOR_CROSSHAIR
|
||||
pointing_hand = C.SAPP_MOUSECURSOR_POINTING_HAND
|
||||
resize_ew = C.SAPP_MOUSECURSOR_RESIZE_EW
|
||||
resize_ns = C.SAPP_MOUSECURSOR_RESIZE_NS
|
||||
resize_nwse = C.SAPP_MOUSECURSOR_RESIZE_NWSE
|
||||
resize_nesw = C.SAPP_MOUSECURSOR_RESIZE_NESW
|
||||
resize_all = C.SAPP_MOUSECURSOR_RESIZE_ALL
|
||||
not_allowed = C.SAPP_MOUSECURSOR_NOT_ALLOWED
|
||||
}
|
||||
|
||||
pub enum Modifier {
|
||||
shift = 1 //(1<<0)
|
||||
ctrl = 2 //(1<<1)
|
||||
alt = 4 //(1<<2)
|
||||
super = 8 //(1<<3)
|
||||
lmb = 0x100
|
||||
rmb = 0x200
|
||||
mmb = 0x400
|
||||
}
|
||||
|
||||
pub enum KeyCode {
|
||||
invalid = 0
|
||||
space = 32
|
||||
apostrophe = 39 //'
|
||||
comma = 44 //,
|
||||
minus = 45 //-
|
||||
period = 46 //.
|
||||
slash = 47 ///
|
||||
_0 = 48
|
||||
_1 = 49
|
||||
_2 = 50
|
||||
_3 = 51
|
||||
_4 = 52
|
||||
_5 = 53
|
||||
_6 = 54
|
||||
_7 = 55
|
||||
_8 = 56
|
||||
_9 = 57
|
||||
semicolon = 59 //;
|
||||
equal = 61 //=
|
||||
a = 65
|
||||
b = 66
|
||||
c = 67
|
||||
d = 68
|
||||
e = 69
|
||||
f = 70
|
||||
g = 71
|
||||
h = 72
|
||||
i = 73
|
||||
j = 74
|
||||
k = 75
|
||||
l = 76
|
||||
m = 77
|
||||
n = 78
|
||||
o = 79
|
||||
p = 80
|
||||
q = 81
|
||||
r = 82
|
||||
s = 83
|
||||
t = 84
|
||||
u = 85
|
||||
v = 86
|
||||
w = 87
|
||||
x = 88
|
||||
y = 89
|
||||
z = 90
|
||||
left_bracket = 91 //[
|
||||
backslash = 92 //\
|
||||
right_bracket = 93 //]
|
||||
grave_accent = 96 //`
|
||||
world_1 = 161 // non-us #1
|
||||
world_2 = 162 // non-us #2
|
||||
escape = 256
|
||||
enter = 257
|
||||
tab = 258
|
||||
backspace = 259
|
||||
insert = 260
|
||||
delete = 261
|
||||
right = 262
|
||||
left = 263
|
||||
down = 264
|
||||
up = 265
|
||||
page_up = 266
|
||||
page_down = 267
|
||||
home = 268
|
||||
end = 269
|
||||
caps_lock = 280
|
||||
scroll_lock = 281
|
||||
num_lock = 282
|
||||
print_screen = 283
|
||||
pause = 284
|
||||
f1 = 290
|
||||
f2 = 291
|
||||
f3 = 292
|
||||
f4 = 293
|
||||
f5 = 294
|
||||
f6 = 295
|
||||
f7 = 296
|
||||
f8 = 297
|
||||
f9 = 298
|
||||
f10 = 299
|
||||
f11 = 300
|
||||
f12 = 301
|
||||
f13 = 302
|
||||
f14 = 303
|
||||
f15 = 304
|
||||
f16 = 305
|
||||
f17 = 306
|
||||
f18 = 307
|
||||
f19 = 308
|
||||
f20 = 309
|
||||
f21 = 310
|
||||
f22 = 311
|
||||
f23 = 312
|
||||
f24 = 313
|
||||
f25 = 314
|
||||
kp_0 = 320
|
||||
kp_1 = 321
|
||||
kp_2 = 322
|
||||
kp_3 = 323
|
||||
kp_4 = 324
|
||||
kp_5 = 325
|
||||
kp_6 = 326
|
||||
kp_7 = 327
|
||||
kp_8 = 328
|
||||
kp_9 = 329
|
||||
kp_decimal = 330
|
||||
kp_divide = 331
|
||||
kp_multiply = 332
|
||||
kp_subtract = 333
|
||||
kp_add = 334
|
||||
kp_enter = 335
|
||||
kp_equal = 336
|
||||
left_shift = 340
|
||||
left_control = 341
|
||||
left_alt = 342
|
||||
left_super = 343
|
||||
right_shift = 344
|
||||
right_control = 345
|
||||
right_alt = 346
|
||||
right_super = 347
|
||||
menu = 348
|
||||
}
|
||||
|
||||
// TouchToolType is an Android specific 'tool type' enum for touch events.
|
||||
// This lets the application check what type of input device was used for touch events.
|
||||
// NOTE: the values must remain in sync with the corresponding Android SDK type, so don't change those.
|
||||
// See https://developer.android.com/reference/android/view/MotionEvent#TOOL_TYPE_UNKNOWN
|
||||
pub enum TouchToolType {
|
||||
unknown
|
||||
finger
|
||||
stylus
|
||||
mouse
|
||||
eraser
|
||||
palm
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
@[has_globals]
|
||||
module sapp
|
||||
|
||||
import sokol.gfx
|
||||
import sokol.memory
|
||||
|
||||
// Android needs a global reference to `g_desc`
|
||||
__global g_desc C.sapp_desc
|
||||
|
||||
pub fn create_desc() gfx.Desc {
|
||||
return gfx.Desc{
|
||||
environment: glue_environment()
|
||||
image_pool_size: 1000
|
||||
}
|
||||
}
|
||||
|
||||
// create_default_pass creates a default `gfx.Pass` compatible with `sapp` and `sokol.gfx.begin_pass/1`.
|
||||
pub fn create_default_pass(action gfx.PassAction) gfx.Pass {
|
||||
return gfx.Pass{
|
||||
action: action
|
||||
swapchain: glue_swapchain()
|
||||
}
|
||||
}
|
||||
|
||||
// sapp_to_gfx_pixelformat converts an sapp_pixel_format int to a gfx.PixelFormat.
|
||||
// The sapp and gfx pixel format enums have different integer values, so a direct
|
||||
// cast is incorrect.
|
||||
fn sapp_to_gfx_pixelformat(sapp_fmt int) gfx.PixelFormat {
|
||||
// sapp_pixel_format: _DEFAULT=0, NONE=1, RGBA8=2, SRGB8A8=3, BGRA8=4, SBGRA8=5, DEPTH=6, DEPTH_STENCIL=7
|
||||
return match sapp_fmt {
|
||||
1 { gfx.PixelFormat.none }
|
||||
2 { gfx.PixelFormat.rgba8 }
|
||||
3 { gfx.PixelFormat.srgb8a8 }
|
||||
4 { gfx.PixelFormat.bgra8 }
|
||||
5 { gfx.PixelFormat.bgra8 } // sbgra8 has no gfx equivalent, use bgra8
|
||||
6 { gfx.PixelFormat.depth }
|
||||
7 { gfx.PixelFormat.depth_stencil }
|
||||
else { gfx.PixelFormat.none }
|
||||
}
|
||||
}
|
||||
|
||||
// glue_environment returns a `gfx.Environment` compatible for use with `sapp` specific `gfx.Pass`es.
|
||||
// The retuned `gfx.Environment` can be used when rendering via `sapp`.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
pub fn glue_environment() gfx.Environment {
|
||||
sapp_env := C.sapp_get_environment()
|
||||
mut env := gfx.Environment{}
|
||||
unsafe { vmemset(&env, 0, int(sizeof(env))) }
|
||||
env.defaults.color_format = sapp_to_gfx_pixelformat(sapp_env.defaults.color_format)
|
||||
env.defaults.depth_format = sapp_to_gfx_pixelformat(sapp_env.defaults.depth_format)
|
||||
env.defaults.sample_count = sapp_env.defaults.sample_count
|
||||
$if macos && !darwin_sokol_glcore33 ? {
|
||||
env.metal.device = sapp_env.metal.device
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
// glue_swapchain returns a `gfx.Swapchain` compatible for use with `sapp` specific display/rendering `gfx.Pass`es.
|
||||
// The retuned `gfx.Swapchain` can be used when rendering via `sapp`.
|
||||
// See also: documentation at the top of thirdparty/sokol/sokol_gfx.h
|
||||
pub fn glue_swapchain() gfx.Swapchain {
|
||||
sapp_sc := C.sapp_get_swapchain()
|
||||
mut swapchain := gfx.Swapchain{}
|
||||
unsafe { vmemset(&swapchain, 0, int(sizeof(swapchain))) }
|
||||
swapchain.width = sapp_sc.width
|
||||
swapchain.height = sapp_sc.height
|
||||
swapchain.sample_count = sapp_sc.sample_count
|
||||
swapchain.color_format = sapp_to_gfx_pixelformat(sapp_sc.color_format)
|
||||
swapchain.depth_format = sapp_to_gfx_pixelformat(sapp_sc.depth_format)
|
||||
$if macos && !darwin_sokol_glcore33 ? {
|
||||
swapchain.metal.current_drawable = sapp_sc.metal.current_drawable
|
||||
swapchain.metal.depth_stencil_texture = sapp_sc.metal.depth_stencil_texture
|
||||
swapchain.metal.msaa_color_texture = sapp_sc.metal.msaa_color_texture
|
||||
} $else {
|
||||
swapchain.gl.framebuffer = sapp_sc.gl.framebuffer
|
||||
}
|
||||
return swapchain
|
||||
}
|
||||
|
||||
// returns true after sokol-app has been initialized
|
||||
@[inline]
|
||||
pub fn isvalid() bool {
|
||||
return C.sapp_isvalid()
|
||||
}
|
||||
|
||||
// returns the current framebuffer width in pixels
|
||||
@[inline]
|
||||
pub fn width() int {
|
||||
return C.sapp_width()
|
||||
}
|
||||
|
||||
// returns the current framebuffer height in pixels
|
||||
@[inline]
|
||||
pub fn height() int {
|
||||
return C.sapp_height()
|
||||
}
|
||||
|
||||
// color_format gets default framebuffer color pixel format
|
||||
@[inline]
|
||||
pub fn color_format() int {
|
||||
return C.sapp_color_format()
|
||||
}
|
||||
|
||||
// depth_format gets default framebuffer depth pixel format
|
||||
@[inline]
|
||||
pub fn depth_format() int {
|
||||
return C.sapp_depth_format()
|
||||
}
|
||||
|
||||
// sample_count gets default framebuffer sample count
|
||||
@[inline]
|
||||
pub fn sample_count() int {
|
||||
return C.sapp_sample_count()
|
||||
}
|
||||
|
||||
// returns true when high_dpi was requested and actually running in a high-dpi scenario
|
||||
@[inline]
|
||||
pub fn high_dpi() bool {
|
||||
return C.sapp_high_dpi()
|
||||
}
|
||||
|
||||
// returns the dpi scaling factor (window pixels to framebuffer pixels)
|
||||
@[inline]
|
||||
pub fn dpi_scale() f32 {
|
||||
return C.sapp_dpi_scale()
|
||||
}
|
||||
|
||||
// show or hide the mobile device onscreen keyboard
|
||||
@[inline]
|
||||
pub fn show_keyboard(visible bool) {
|
||||
C.sapp_show_keyboard(visible)
|
||||
}
|
||||
|
||||
// return true if the mobile device onscreen keyboard is currently shown
|
||||
@[inline]
|
||||
pub fn keyboard_shown() bool {
|
||||
return C.sapp_keyboard_shown()
|
||||
}
|
||||
|
||||
// show or hide the mouse cursor
|
||||
@[inline]
|
||||
pub fn show_mouse(visible bool) {
|
||||
C.sapp_show_mouse(visible)
|
||||
}
|
||||
|
||||
// set mouse cursor
|
||||
@[inline]
|
||||
pub fn set_mouse_cursor(cursor MouseCursor) {
|
||||
C.sapp_set_mouse_cursor(cursor)
|
||||
}
|
||||
|
||||
// show or hide the mouse cursor
|
||||
@[inline]
|
||||
pub fn mouse_shown() bool {
|
||||
return C.sapp_mouse_shown()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn lock_mouse(locked bool) {
|
||||
C.sapp_lock_mouse(locked)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn mouse_locked() bool {
|
||||
return C.sapp_mouse_locked()
|
||||
}
|
||||
|
||||
// return the userdata pointer optionally provided in sapp_desc
|
||||
@[inline]
|
||||
pub fn userdata() voidptr {
|
||||
return C.sapp_userdata()
|
||||
}
|
||||
|
||||
// return a copy of the sapp_desc structure
|
||||
@[inline]
|
||||
pub fn query_desc() Desc {
|
||||
return C.sapp_query_desc()
|
||||
}
|
||||
|
||||
// initiate a "soft quit" (sends SAPP_EVENTTYPE_QUIT_REQUESTED)
|
||||
@[inline]
|
||||
pub fn request_quit() {
|
||||
C.sapp_request_quit()
|
||||
}
|
||||
|
||||
// cancel a pending quit (when SAPP_EVENTTYPE_QUIT_REQUESTED has been received)
|
||||
@[inline]
|
||||
pub fn cancel_quit() {
|
||||
C.sapp_cancel_quit()
|
||||
}
|
||||
|
||||
// initiate a "hard quit" (quit application without sending SAPP_EVENTTYPE_QUIT_REQUESTED)
|
||||
@[inline]
|
||||
pub fn quit() {
|
||||
C.sapp_quit()
|
||||
}
|
||||
|
||||
// call from inside event callback to consume the current event (don't forward to platform)
|
||||
@[inline]
|
||||
pub fn consume_event() {
|
||||
C.sapp_consume_event()
|
||||
}
|
||||
|
||||
// get the current frame counter (for comparison with sapp_event.frame_count)
|
||||
@[inline]
|
||||
pub fn frame_count() u64 {
|
||||
return C.sapp_frame_count()
|
||||
}
|
||||
|
||||
// get an averaged/smoothed frame duration in seconds
|
||||
@[inline]
|
||||
pub fn frame_duration() f64 {
|
||||
return C.sapp_frame_duration()
|
||||
}
|
||||
|
||||
// write string into clipboard
|
||||
@[inline]
|
||||
pub fn set_clipboard_string(str &u8) {
|
||||
C.sapp_set_clipboard_string(&char(str))
|
||||
}
|
||||
|
||||
// read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED)
|
||||
@[inline]
|
||||
pub fn get_clipboard_string() &char {
|
||||
return &char(C.sapp_get_clipboard_string())
|
||||
}
|
||||
|
||||
// special run-function for SOKOL_NO_ENTRY (in standard mode this is an empty stub)
|
||||
pub fn run(desc &Desc) {
|
||||
if desc.allocator.alloc_fn == unsafe { nil } && desc.allocator.free_fn == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.allocator.alloc_fn = memory.salloc
|
||||
desc.allocator.free_fn = memory.sfree
|
||||
desc.allocator.user_data = voidptr(0x10005a44)
|
||||
}
|
||||
}
|
||||
if desc.logger.func == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.logger.func = memory.slog
|
||||
}
|
||||
}
|
||||
g_desc = *desc
|
||||
C.sapp_run(desc)
|
||||
}
|
||||
|
||||
// HTML5: enable or disable the hardwired "Leave Site?" dialog box
|
||||
@[inline]
|
||||
pub fn html5_ask_leave_site(ask bool) {
|
||||
C.sapp_html5_ask_leave_site(ask)
|
||||
}
|
||||
|
||||
// macOS: get ARC-bridged pointer to macOS NSWindow
|
||||
@[inline]
|
||||
pub fn macos_get_window() voidptr {
|
||||
return voidptr(C.sapp_macos_get_window())
|
||||
}
|
||||
|
||||
// iOS: get ARC-bridged pointer to iOS UIWindow
|
||||
@[inline]
|
||||
pub fn ios_get_window() voidptr {
|
||||
return voidptr(C.sapp_ios_get_window())
|
||||
}
|
||||
|
||||
// Win32: get the HWND window handle
|
||||
@[inline]
|
||||
pub fn win32_get_hwnd() voidptr {
|
||||
return voidptr(C.sapp_win32_get_hwnd())
|
||||
}
|
||||
|
||||
// GL: get framebuffer object
|
||||
@[inline]
|
||||
pub fn gl_get_framebuffer() u32 {
|
||||
return C.sapp_gl_get_framebuffer()
|
||||
}
|
||||
|
||||
// X11: get display handle
|
||||
@[inline]
|
||||
pub fn x11_get_display() voidptr {
|
||||
return voidptr(C.sapp_x11_get_display())
|
||||
}
|
||||
|
||||
// X11: get window handle
|
||||
@[inline]
|
||||
pub fn x11_get_window() voidptr {
|
||||
return voidptr(C.sapp_x11_get_window())
|
||||
}
|
||||
|
||||
// Android: get native activity handle
|
||||
@[inline]
|
||||
pub fn android_get_native_activity() voidptr {
|
||||
return voidptr(C.sapp_android_get_native_activity())
|
||||
}
|
||||
|
||||
// Toggle full screen
|
||||
@[inline]
|
||||
pub fn toggle_fullscreen() {
|
||||
C.sapp_toggle_fullscreen()
|
||||
}
|
||||
|
||||
// Check if full screen rendering
|
||||
@[inline]
|
||||
pub fn is_fullscreen() bool {
|
||||
return C.sapp_is_fullscreen()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn get_num_dropped_files() int {
|
||||
return C.sapp_get_num_dropped_files()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn get_dropped_file_path(index int) string {
|
||||
unsafe {
|
||||
return cstring_to_vstring(C.sapp_get_dropped_file_path(index))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
module sapp
|
||||
|
||||
import sokol.memory
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_allocator {
|
||||
pub mut:
|
||||
alloc_fn memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free_fn memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_logger {
|
||||
pub mut:
|
||||
func memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
module sapp
|
||||
|
||||
// EGL initialization and teardown.
|
||||
// Shared between Wayland and X11 backends.
|
||||
|
||||
fn sapp_egl_choose_config() EGLConfig {
|
||||
samples := if g_sapp_state.desc.sample_count > 1 {
|
||||
EGLint(g_sapp_state.desc.sample_count)
|
||||
} else {
|
||||
EGLint(0)
|
||||
}
|
||||
alpha_size := if g_sapp_state.desc.alpha { EGLint(8) } else { EGLint(0) }
|
||||
sample_buffers := if g_sapp_state.desc.sample_count > 1 { EGLint(1) } else { EGLint(0) }
|
||||
|
||||
config_attrs := [
|
||||
egl_surface_type,
|
||||
egl_window_bit,
|
||||
egl_renderable_type,
|
||||
egl_opengl_bit,
|
||||
egl_red_size,
|
||||
EGLint(8),
|
||||
egl_green_size,
|
||||
EGLint(8),
|
||||
egl_blue_size,
|
||||
EGLint(8),
|
||||
egl_alpha_size,
|
||||
alpha_size,
|
||||
egl_depth_size,
|
||||
EGLint(24),
|
||||
egl_stencil_size,
|
||||
EGLint(8),
|
||||
egl_sample_buffers,
|
||||
sample_buffers,
|
||||
egl_samples,
|
||||
samples,
|
||||
egl_none,
|
||||
]!
|
||||
|
||||
mut egl_configs := unsafe { [32]EGLConfig{} }
|
||||
mut config_count := EGLint(0)
|
||||
if C.eglChooseConfig(g_sapp_state.egl.display, &config_attrs[0], &egl_configs[0], 32, &config_count) == 0
|
||||
|| config_count == 0 {
|
||||
eprintln('sokol_app: EGL: no configs found')
|
||||
return egl_configs[0]
|
||||
}
|
||||
|
||||
mut config := egl_configs[0]
|
||||
for i in 0 .. int(config_count) {
|
||||
c := egl_configs[i]
|
||||
mut r := EGLint(0)
|
||||
mut g := EGLint(0)
|
||||
mut b := EGLint(0)
|
||||
mut a := EGLint(0)
|
||||
mut d := EGLint(0)
|
||||
mut s := EGLint(0)
|
||||
mut n := EGLint(0)
|
||||
if C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_red_size, &r) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_green_size, &g) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_blue_size, &b) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_alpha_size, &a) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_depth_size, &d) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_stencil_size, &s) != 0
|
||||
&& C.eglGetConfigAttrib(g_sapp_state.egl.display, c, egl_samples, &n) != 0 && r == 8
|
||||
&& g == 8 && b == 8 && a == alpha_size && d == 24 && s == 8 && n == samples {
|
||||
config = c
|
||||
break
|
||||
}
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
fn sapp_egl_create_context(config EGLConfig) {
|
||||
gl_major := if g_sapp_state.desc.gl.major_version != 0 {
|
||||
g_sapp_state.desc.gl.major_version
|
||||
} else {
|
||||
4
|
||||
}
|
||||
gl_minor := if g_sapp_state.desc.gl.minor_version != 0 {
|
||||
g_sapp_state.desc.gl.minor_version
|
||||
} else {
|
||||
1
|
||||
}
|
||||
|
||||
ctx_attrs := [
|
||||
egl_context_major_version,
|
||||
EGLint(gl_major),
|
||||
egl_context_minor_version,
|
||||
EGLint(gl_minor),
|
||||
egl_context_opengl_profile_mask,
|
||||
egl_context_opengl_core_profile_bit,
|
||||
egl_none,
|
||||
]!
|
||||
|
||||
g_sapp_state.egl.context = C.eglCreateContext(g_sapp_state.egl.display, config, unsafe { nil },
|
||||
&ctx_attrs[0])
|
||||
if g_sapp_state.egl.context == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to create context')
|
||||
}
|
||||
}
|
||||
|
||||
fn sapp_egl_create_surface(native_window voidptr) {
|
||||
config := sapp_egl_choose_config()
|
||||
g_sapp_state.egl.config = config
|
||||
g_sapp_state.egl.surface = C.eglCreateWindowSurface(g_sapp_state.egl.display, config,
|
||||
native_window, unsafe { nil })
|
||||
if g_sapp_state.egl.surface == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to create window surface')
|
||||
}
|
||||
if g_sapp_state.egl.context == unsafe { nil } {
|
||||
sapp_egl_create_context(config)
|
||||
}
|
||||
}
|
||||
|
||||
fn sapp_egl_make_current() {
|
||||
if C.eglMakeCurrent(g_sapp_state.egl.display, g_sapp_state.egl.surface,
|
||||
g_sapp_state.egl.surface, g_sapp_state.egl.context) == 0 {
|
||||
eprintln('sokol_app: EGL: eglMakeCurrent failed')
|
||||
}
|
||||
mut fb := i32(0)
|
||||
C.glGetIntegerv(gl_framebuffer_binding, &fb)
|
||||
g_sapp_state.gl.framebuffer = u32(fb)
|
||||
C.eglSwapInterval(g_sapp_state.egl.display, EGLint(g_sapp_state.swap_interval))
|
||||
}
|
||||
|
||||
$if sokol_wayland ? {
|
||||
fn sapp_egl_init_wayland() {
|
||||
if C.eglBindAPI(egl_opengl_api) == 0 {
|
||||
eprintln('sokol_app: EGL: failed to bind OpenGL API')
|
||||
}
|
||||
|
||||
g_sapp_state.egl.display = C.eglGetDisplay(voidptr(g_sapp_state.wl.display))
|
||||
if g_sapp_state.egl.display == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to get display')
|
||||
}
|
||||
|
||||
mut major := EGLint(0)
|
||||
mut minor := EGLint(0)
|
||||
if C.eglInitialize(g_sapp_state.egl.display, &major, &minor) == 0 {
|
||||
eprintln('sokol_app: EGL: failed to initialize')
|
||||
}
|
||||
g_sapp_state.gl.major = int(major)
|
||||
g_sapp_state.gl.minor = int(minor)
|
||||
}
|
||||
}
|
||||
|
||||
fn sapp_egl_init_x11() {
|
||||
if C.eglBindAPI(egl_opengl_api) == 0 {
|
||||
eprintln('sokol_app: EGL: failed to bind OpenGL API')
|
||||
}
|
||||
|
||||
g_sapp_state.egl.display = C.eglGetDisplay(voidptr(g_sapp_state.x11.display))
|
||||
if g_sapp_state.egl.display == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to get display')
|
||||
}
|
||||
|
||||
mut major := EGLint(0)
|
||||
mut minor := EGLint(0)
|
||||
if C.eglInitialize(g_sapp_state.egl.display, &major, &minor) == 0 {
|
||||
eprintln('sokol_app: EGL: failed to initialize')
|
||||
}
|
||||
g_sapp_state.gl.major = int(major)
|
||||
g_sapp_state.gl.minor = int(minor)
|
||||
|
||||
config := sapp_egl_choose_config()
|
||||
|
||||
mut visual_id := EGLint(0)
|
||||
if C.eglGetConfigAttrib(g_sapp_state.egl.display, config, EGLint(0x302E), &visual_id) == 0 {
|
||||
eprintln('sokol_app: EGL: failed to get native visual ID')
|
||||
}
|
||||
|
||||
mut visual_info_template := C.XVisualInfo{}
|
||||
visual_info_template.visualid = VisualID(visual_id)
|
||||
|
||||
mut num_visuals := 0
|
||||
visual_info := C.XGetVisualInfo(g_sapp_state.x11.display, visual_id_mask,
|
||||
&visual_info_template, &num_visuals)
|
||||
if visual_info == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to get visual info')
|
||||
}
|
||||
|
||||
x11_create_window(visual_info.visual, visual_info.depth)
|
||||
C.XFree(visual_info)
|
||||
|
||||
g_sapp_state.egl.surface = C.eglCreateWindowSurface(g_sapp_state.egl.display, config,
|
||||
EGLNativeWindowType(g_sapp_state.x11.window), unsafe { nil })
|
||||
if g_sapp_state.egl.surface == unsafe { nil } {
|
||||
eprintln('sokol_app: EGL: failed to create window surface')
|
||||
}
|
||||
|
||||
sapp_egl_create_context(config)
|
||||
sapp_egl_make_current()
|
||||
}
|
||||
|
||||
fn sapp_egl_destroy() {
|
||||
if g_sapp_state.egl.display != unsafe { nil } {
|
||||
C.eglMakeCurrent(g_sapp_state.egl.display, unsafe { nil }, unsafe { nil }, unsafe { nil })
|
||||
|
||||
if g_sapp_state.egl.context != unsafe { nil } {
|
||||
C.eglDestroyContext(g_sapp_state.egl.display, g_sapp_state.egl.context)
|
||||
g_sapp_state.egl.context = unsafe { nil }
|
||||
}
|
||||
|
||||
if g_sapp_state.egl.surface != unsafe { nil } {
|
||||
C.eglDestroySurface(g_sapp_state.egl.display, g_sapp_state.egl.surface)
|
||||
g_sapp_state.egl.surface = unsafe { nil }
|
||||
}
|
||||
|
||||
C.eglTerminate(g_sapp_state.egl.display)
|
||||
g_sapp_state.egl.display = unsafe { nil }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
module sapp
|
||||
|
||||
#define SOKOL_VALIDATE_NON_FATAL 1
|
||||
|
||||
// returns true after sokol-app has been initialized
|
||||
fn C.sapp_isvalid() bool
|
||||
|
||||
// returns the current framebuffer width in pixels
|
||||
fn C.sapp_width() i32
|
||||
fn C.sapp_widthf() f32
|
||||
|
||||
// returns the current framebuffer height in pixels
|
||||
fn C.sapp_height() i32
|
||||
fn C.sapp_heightf() f32
|
||||
|
||||
// get default framebuffer color pixel format
|
||||
fn C.sapp_color_format() i32
|
||||
|
||||
// get default framebuffer depth pixel format
|
||||
fn C.sapp_depth_format() i32
|
||||
|
||||
// get default framebuffer sample count
|
||||
fn C.sapp_sample_count() i32
|
||||
|
||||
// returns true when high_dpi was requested and actually running in a high-dpi scenario
|
||||
fn C.sapp_high_dpi() bool
|
||||
|
||||
// returns the dpi scaling factor (window pixels to framebuffer pixels)
|
||||
fn C.sapp_dpi_scale() f32
|
||||
|
||||
// show or hide the mobile device onscreen keyboard
|
||||
fn C.sapp_show_keyboard(visible bool)
|
||||
|
||||
// return true if the mobile device onscreen keyboard is currently shown
|
||||
fn C.sapp_keyboard_shown() bool
|
||||
|
||||
// Check if full screen rendering
|
||||
fn C.sapp_is_fullscreen() bool
|
||||
|
||||
// Toggle full screen
|
||||
fn C.sapp_toggle_fullscreen()
|
||||
|
||||
// show or hide the mouse cursor
|
||||
fn C.sapp_show_mouse(visible bool)
|
||||
|
||||
// return true if the mouse cursor is shown
|
||||
fn C.sapp_mouse_shown() bool
|
||||
|
||||
// set mouse cursor
|
||||
fn C.sapp_set_mouse_cursor(cursor MouseCursor)
|
||||
|
||||
// get current mouse cursor type
|
||||
fn C.sapp_get_mouse_cursor() MouseCursor
|
||||
|
||||
// bind a custom mouse cursor image to a cursor type, returns the cursor type
|
||||
fn C.sapp_bind_mouse_cursor_image(cursor MouseCursor, desc &ImageDesc) MouseCursor
|
||||
|
||||
// unbind a custom mouse cursor image
|
||||
fn C.sapp_unbind_mouse_cursor_image(cursor MouseCursor)
|
||||
|
||||
// lock or unlock the mouse cursor
|
||||
fn C.sapp_lock_mouse(locked bool)
|
||||
|
||||
// return true if the mouse cursor is locked
|
||||
fn C.sapp_mouse_locked() bool
|
||||
|
||||
// return the userdata pointer optionally provided in sapp_desc
|
||||
fn C.sapp_userdata() voidptr
|
||||
|
||||
// return a copy of the sapp_desc structure
|
||||
fn C.sapp_query_desc() Desc
|
||||
|
||||
// initiate a "soft quit" (sends SAPP_EVENTTYPE_QUIT_REQUESTED)
|
||||
fn C.sapp_request_quit()
|
||||
|
||||
// cancel a pending quit (when SAPP_EVENTTYPE_QUIT_REQUESTED has been received)
|
||||
fn C.sapp_cancel_quit()
|
||||
|
||||
// intiate a "hard quit" (quit application without sending SAPP_EVENTTYPE_QUIT_REQUESTED)
|
||||
fn C.sapp_quit()
|
||||
|
||||
// call from inside event callback to consume the current event (don't forward to platform)
|
||||
fn C.sapp_consume_event()
|
||||
|
||||
// get the current frame counter (for comparison with sapp_event.frame_count)
|
||||
fn C.sapp_frame_count() u64
|
||||
|
||||
// get an averaged/smoothed frame duration in seconds
|
||||
fn C.sapp_frame_duration() f64
|
||||
|
||||
// write string into clipboard
|
||||
fn C.sapp_set_clipboard_string(const_str &char)
|
||||
|
||||
// read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED)
|
||||
fn C.sapp_get_clipboard_string() &char
|
||||
|
||||
// set the window title (only on desktop platforms)
|
||||
fn C.sapp_set_window_title(&char)
|
||||
|
||||
// set the window icon (only on Windows and Linux)
|
||||
fn C.sapp_set_icon(const_icon_desc &IconDesc)
|
||||
|
||||
// Get number of dropped files
|
||||
fn C.sapp_get_num_dropped_files() i32
|
||||
|
||||
// Get the file path of the dropped file
|
||||
fn C.sapp_get_dropped_file_path(i32) &char
|
||||
|
||||
// special run-function for SOKOL_NO_ENTRY (in standard mode this is an empty stub)
|
||||
fn C.sapp_run(const_desc &Desc) i32
|
||||
|
||||
// get runtime environment information
|
||||
fn C.sapp_get_environment() Environment
|
||||
|
||||
// get current frame's swapchain information (call once per frame!)
|
||||
fn C.sapp_get_swapchain() Swapchain
|
||||
|
||||
// EGL: get EGLDisplay object
|
||||
fn C.sapp_egl_get_display() voidptr
|
||||
|
||||
// EGL: get EGLContext object
|
||||
fn C.sapp_egl_get_context() voidptr
|
||||
|
||||
// HTML5: enable or disable the hardwired "Leave Site?" dialog box
|
||||
fn C.sapp_html5_ask_leave_site(ask bool)
|
||||
|
||||
// HTML5: get byte size of a dropped file
|
||||
fn C.sapp_html5_get_dropped_file_size(index i32) u32
|
||||
|
||||
// macOS: get ARC-bridged pointer to macOS NSWindow
|
||||
fn C.sapp_macos_get_window() voidptr
|
||||
|
||||
// iOS: get ARC-bridged pointer to iOS UIWindow
|
||||
fn C.sapp_ios_get_window() voidptr
|
||||
|
||||
// D3D11: get pointer to IDXGISwapChain object
|
||||
fn C.sapp_d3d11_get_swap_chain() voidptr
|
||||
|
||||
// Win32: get the HWND window handle
|
||||
fn C.sapp_win32_get_hwnd() voidptr
|
||||
|
||||
// GL: get major version
|
||||
fn C.sapp_gl_get_major_version() i32
|
||||
|
||||
// GL: get minor version
|
||||
fn C.sapp_gl_get_minor_version() i32
|
||||
|
||||
// GL: return true if the context is GLES
|
||||
fn C.sapp_gl_is_gles() bool
|
||||
|
||||
// GL: get framebuffer object
|
||||
fn C.sapp_gl_get_framebuffer() u32
|
||||
|
||||
// X11: get Window
|
||||
fn C.sapp_x11_get_window() voidptr
|
||||
|
||||
// X11: get Display
|
||||
fn C.sapp_x11_get_display() voidptr
|
||||
|
||||
// Android: get native activity handle
|
||||
fn C.sapp_android_get_native_activity() voidptr
|
||||
|
||||
// V-specific: read RGBA pixels from the OpenGL framebuffer
|
||||
fn C.v_sapp_gl_read_rgba_pixels(x i32, y i32, width i32, height i32, pixels charptr)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,62 @@
|
||||
module sapp
|
||||
|
||||
// Shared state structs for the V sokol_app backends.
|
||||
// Platform-specific state (SappState, g_sapp_state, SappWayland, SappWin32, etc.)
|
||||
// lives in sapp_state_linux.v / sapp_state_windows.v respectively.
|
||||
|
||||
const ring_num_slots = 256
|
||||
const max_title_length = 128
|
||||
const mousecursor_num = 27
|
||||
|
||||
// Timing state for frame duration averaging
|
||||
struct SappTiming {
|
||||
mut:
|
||||
last f64
|
||||
accum f64
|
||||
avg f64
|
||||
spike_count int
|
||||
num int
|
||||
ring_head int
|
||||
ring_tail int
|
||||
ring_buf [ring_num_slots]f64
|
||||
}
|
||||
|
||||
// Mouse state
|
||||
struct SappMouse {
|
||||
mut:
|
||||
x f32
|
||||
y f32
|
||||
dx f32
|
||||
dy f32
|
||||
shown bool
|
||||
locked bool
|
||||
pos_valid bool
|
||||
current_cursor MouseCursor
|
||||
}
|
||||
|
||||
// Clipboard state
|
||||
struct SappClipboard {
|
||||
mut:
|
||||
enabled bool
|
||||
buf_size int
|
||||
buffer &char = unsafe { nil }
|
||||
}
|
||||
|
||||
// Drag and drop state
|
||||
struct SappDrop {
|
||||
mut:
|
||||
enabled bool
|
||||
max_files int
|
||||
max_path_length int
|
||||
num_files int
|
||||
buf_size int
|
||||
buffer &char = unsafe { nil }
|
||||
}
|
||||
|
||||
// GL state
|
||||
struct SappGl {
|
||||
mut:
|
||||
framebuffer u32
|
||||
major int
|
||||
minor int
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
@[has_globals]
|
||||
module sapp
|
||||
|
||||
// Linux-specific state structs for the V sokol_app backend.
|
||||
// Shared state (SappTiming, SappMouse, etc.) is in sapp_state.v.
|
||||
|
||||
// X11 and XKB share keypad/navigation keysyms. Keep the stateful keypad mapping in one place so
|
||||
// Num Lock can flip keypad arrows between navigation keys and keypad digits consistently.
|
||||
fn linux_translate_navigation_or_keypad_keysym(keysym u32) KeyCode {
|
||||
return match keysym {
|
||||
0xff63, 0xff9e { .insert }
|
||||
0xffff, 0xff9f { .delete }
|
||||
0xff50, 0xff95 { .home }
|
||||
0xff57, 0xff9c { .end }
|
||||
0xff55, 0xff9a { .page_up }
|
||||
0xff56, 0xff9b { .page_down }
|
||||
0xff51, 0xff96 { .left }
|
||||
0xff53, 0xff98 { .right }
|
||||
0xff52, 0xff97 { .up }
|
||||
0xff54, 0xff99 { .down }
|
||||
0xffb0 { .kp_0 }
|
||||
0xffb1 { .kp_1 }
|
||||
0xffb2 { .kp_2 }
|
||||
0xffb3 { .kp_3 }
|
||||
0xff9d, 0xffb5 { .kp_5 }
|
||||
0xffb4 { .kp_4 }
|
||||
0xffb6 { .kp_6 }
|
||||
0xffb7 { .kp_7 }
|
||||
0xffb8 { .kp_8 }
|
||||
0xffb9 { .kp_9 }
|
||||
0xffac, 0xffae { .kp_decimal }
|
||||
0xffaf { .kp_divide }
|
||||
0xffaa { .kp_multiply }
|
||||
0xffad { .kp_subtract }
|
||||
0xffab { .kp_add }
|
||||
0xff8d { .kp_enter }
|
||||
0xffbd { .kp_equal }
|
||||
else { .invalid }
|
||||
}
|
||||
}
|
||||
|
||||
// Wayland-specific state (only compiled when -d sokol_wayland is used)
|
||||
$if sokol_wayland ? {
|
||||
struct SappWayland {
|
||||
mut:
|
||||
// Core Wayland objects
|
||||
display &C.wl_display = unsafe { nil }
|
||||
registry &C.wl_registry = unsafe { nil }
|
||||
compositor &C.wl_compositor = unsafe { nil }
|
||||
surface &C.wl_surface = unsafe { nil }
|
||||
egl_window &C.wl_egl_window = unsafe { nil }
|
||||
shm &C.wl_shm = unsafe { nil }
|
||||
// XDG shell
|
||||
xdg_wm_base &C.xdg_wm_base = unsafe { nil }
|
||||
xdg_surface &C.xdg_surface = unsafe { nil }
|
||||
xdg_toplevel &C.xdg_toplevel = unsafe { nil }
|
||||
// Input
|
||||
seat &C.wl_seat = unsafe { nil }
|
||||
pointer &C.wl_pointer = unsafe { nil }
|
||||
keyboard &C.wl_keyboard = unsafe { nil }
|
||||
touch &C.wl_touch = unsafe { nil }
|
||||
seat_version u32
|
||||
// Pointer constraints
|
||||
pointer_constraints &C.zwp_pointer_constraints_v1 = unsafe { nil }
|
||||
locked_pointer &C.zwp_locked_pointer_v1 = unsafe { nil }
|
||||
relative_pointer_mgr &C.zwp_relative_pointer_manager_v1 = unsafe { nil }
|
||||
relative_pointer &C.zwp_relative_pointer_v1 = unsafe { nil }
|
||||
// XKB keyboard handling
|
||||
xkb_context &C.xkb_context = unsafe { nil }
|
||||
xkb_keymap &C.xkb_keymap = unsafe { nil }
|
||||
xkb_state &C.xkb_state = unsafe { nil }
|
||||
xkb_compose_table &C.xkb_compose_table = unsafe { nil }
|
||||
xkb_compose_state &C.xkb_compose_state = unsafe { nil }
|
||||
// Cursor
|
||||
cursor_shape_manager &C.wp_cursor_shape_manager_v1 = unsafe { nil }
|
||||
cursor_shape_device &C.wp_cursor_shape_device_v1 = unsafe { nil }
|
||||
cursor_theme &C.wl_cursor_theme = unsafe { nil }
|
||||
cursor_default &C.wl_cursor = unsafe { nil }
|
||||
cursor_surface &C.wl_surface = unsafe { nil }
|
||||
cursor_size int
|
||||
// Fractional scale
|
||||
fractional_scale_mgr &C.wp_fractional_scale_manager_v1 = unsafe { nil }
|
||||
fractional_scale &C.wp_fractional_scale_v1 = unsafe { nil }
|
||||
scale_numerator u32
|
||||
// Viewporter
|
||||
viewporter &C.wp_viewporter = unsafe { nil }
|
||||
viewport &C.wp_viewport = unsafe { nil }
|
||||
// Decorations
|
||||
decoration_manager &C.zxdg_decoration_manager_v1 = unsafe { nil }
|
||||
toplevel_decoration &C.zxdg_toplevel_decoration_v1 = unsafe { nil }
|
||||
// Clipboard / data device
|
||||
data_device_manager &C.wl_data_device_manager = unsafe { nil }
|
||||
data_device &C.wl_data_device = unsafe { nil }
|
||||
data_source &C.wl_data_source = unsafe { nil }
|
||||
data_offer &C.wl_data_offer = unsafe { nil }
|
||||
clipboard_string &char = unsafe { nil }
|
||||
clipboard_size int
|
||||
// Window state
|
||||
width int
|
||||
height int
|
||||
fb_width int
|
||||
fb_height int
|
||||
scale f32 = 1.0
|
||||
configured bool
|
||||
closed bool
|
||||
fullscreen bool
|
||||
maximized bool
|
||||
focused bool
|
||||
// Pointer state
|
||||
pointer_x f32
|
||||
pointer_y f32
|
||||
pointer_enter_serial u32
|
||||
// Key repeat
|
||||
key_repeat_rate int = 25
|
||||
key_repeat_delay int = 600
|
||||
key_repeat_timer_fd int = -1
|
||||
key_repeat_keycode u32
|
||||
}
|
||||
} $else {
|
||||
// Dummy struct for non-Wayland builds
|
||||
struct SappWayland {}
|
||||
}
|
||||
|
||||
// X11 XInput extension state
|
||||
struct SappXi {
|
||||
mut:
|
||||
available bool
|
||||
major_opcode int
|
||||
event_base int
|
||||
error_base int
|
||||
major int
|
||||
minor int
|
||||
}
|
||||
|
||||
// X11 XDnD state
|
||||
struct SappXdnd {
|
||||
mut:
|
||||
version i64
|
||||
source Window
|
||||
format Atom
|
||||
xdnd_aware Atom
|
||||
xdnd_enter Atom
|
||||
xdnd_position Atom
|
||||
xdnd_status Atom
|
||||
xdnd_action_copy Atom
|
||||
xdnd_drop Atom
|
||||
xdnd_finished Atom
|
||||
xdnd_selection Atom
|
||||
xdnd_type_list Atom
|
||||
text_uri_list Atom
|
||||
}
|
||||
|
||||
// X11-specific state
|
||||
struct SappX11 {
|
||||
mut:
|
||||
mouse_buttons u8
|
||||
display &C.Display = unsafe { nil }
|
||||
screen int
|
||||
root Window
|
||||
colormap Colormap
|
||||
window Window
|
||||
hidden_cursor Cursor
|
||||
standard_cursors [mousecursor_num]Cursor
|
||||
custom_cursors [mousecursor_num]Cursor
|
||||
window_state int
|
||||
dpi f32
|
||||
error_code u8
|
||||
// X atoms
|
||||
utf8_string Atom
|
||||
clipboard_atom Atom
|
||||
targets Atom
|
||||
wm_protocols Atom
|
||||
wm_delete_window Atom
|
||||
wm_state Atom
|
||||
net_wm_name Atom
|
||||
net_wm_icon_name Atom
|
||||
net_wm_icon Atom
|
||||
net_wm_state Atom
|
||||
net_wm_state_fullscreen Atom
|
||||
// Extensions
|
||||
xi SappXi
|
||||
xdnd SappXdnd
|
||||
// Key repeat tracking (keycodes 0..255)
|
||||
key_repeat [256]bool
|
||||
}
|
||||
|
||||
// EGL state
|
||||
struct SappEgl {
|
||||
mut:
|
||||
display EGLDisplay
|
||||
context EGLContext
|
||||
surface EGLSurface
|
||||
config EGLConfig
|
||||
}
|
||||
|
||||
// Main application state - Linux version with Wayland/X11/EGL backends
|
||||
struct SappState {
|
||||
mut:
|
||||
desc Desc
|
||||
valid bool
|
||||
fullscreen bool
|
||||
first_frame bool
|
||||
init_called bool
|
||||
cleanup_called bool
|
||||
quit_requested bool
|
||||
quit_ordered bool
|
||||
event_consumed bool
|
||||
html5_ask_leave_site bool
|
||||
onscreen_keyboard_shown bool
|
||||
window_width int
|
||||
window_height int
|
||||
framebuffer_width int
|
||||
framebuffer_height int
|
||||
sample_count int
|
||||
swap_interval int
|
||||
dpi_scale f32 = 1.0
|
||||
frame_count u64
|
||||
timing SappTiming
|
||||
event Event
|
||||
mouse SappMouse
|
||||
clipboard SappClipboard
|
||||
drop SappDrop
|
||||
// Platform-specific state
|
||||
wl SappWayland
|
||||
x11 SappX11
|
||||
egl SappEgl
|
||||
gl SappGl
|
||||
// Keycode translation table
|
||||
keycodes [max_keycodes]KeyCode
|
||||
// Window title
|
||||
window_title [max_title_length]u8
|
||||
// V patch
|
||||
v_native_render bool
|
||||
// Custom cursors
|
||||
custom_cursor_bound [mousecursor_num]bool
|
||||
}
|
||||
|
||||
// The global state instance
|
||||
__global g_sapp_state = SappState{}
|
||||
|
||||
// === Shared helper functions ===
|
||||
|
||||
// init_sapp_event initializes an event struct with common fields.
|
||||
fn init_sapp_event(event_type EventType) {
|
||||
unsafe { C.memset(&g_sapp_state.event, 0, int(sizeof(g_sapp_state.event))) }
|
||||
g_sapp_state.event.@type = event_type
|
||||
g_sapp_state.event.frame_count = g_sapp_state.frame_count
|
||||
g_sapp_state.event.mouse_button = .invalid
|
||||
g_sapp_state.event.window_width = g_sapp_state.window_width
|
||||
g_sapp_state.event.window_height = g_sapp_state.window_height
|
||||
g_sapp_state.event.framebuffer_width = g_sapp_state.framebuffer_width
|
||||
g_sapp_state.event.framebuffer_height = g_sapp_state.framebuffer_height
|
||||
g_sapp_state.event.mouse_x = g_sapp_state.mouse.x
|
||||
g_sapp_state.event.mouse_y = g_sapp_state.mouse.y
|
||||
g_sapp_state.event.mouse_dx = g_sapp_state.mouse.dx
|
||||
g_sapp_state.event.mouse_dy = g_sapp_state.mouse.dy
|
||||
}
|
||||
|
||||
// call_sapp_event dispatches the event to the user's callback.
|
||||
fn call_sapp_event(e &Event) bool {
|
||||
if !g_sapp_state.cleanup_called {
|
||||
if g_sapp_state.desc.event_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.event_cb(e)
|
||||
} else if g_sapp_state.desc.event_userdata_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.event_userdata_cb(e, g_sapp_state.desc.user_data)
|
||||
}
|
||||
}
|
||||
if g_sapp_state.event_consumed {
|
||||
g_sapp_state.event_consumed = false
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// sapp_call_init calls the user's init callback.
|
||||
fn sapp_call_init() {
|
||||
if g_sapp_state.desc.init_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.init_cb()
|
||||
} else if g_sapp_state.desc.init_userdata_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.init_userdata_cb(g_sapp_state.desc.user_data)
|
||||
}
|
||||
g_sapp_state.init_called = true
|
||||
}
|
||||
|
||||
// sapp_call_frame calls the user's frame callback.
|
||||
fn sapp_call_frame() {
|
||||
if g_sapp_state.desc.frame_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.frame_cb()
|
||||
} else if g_sapp_state.desc.frame_userdata_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.frame_userdata_cb(g_sapp_state.desc.user_data)
|
||||
}
|
||||
}
|
||||
|
||||
// sapp_call_cleanup calls the user's cleanup callback.
|
||||
fn sapp_call_cleanup() {
|
||||
if !g_sapp_state.cleanup_called {
|
||||
if g_sapp_state.desc.cleanup_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.cleanup_cb()
|
||||
} else if g_sapp_state.desc.cleanup_userdata_cb != unsafe { nil } {
|
||||
g_sapp_state.desc.cleanup_userdata_cb(g_sapp_state.desc.user_data)
|
||||
}
|
||||
g_sapp_state.cleanup_called = true
|
||||
}
|
||||
}
|
||||
|
||||
// sapp_do_frame handles the per-frame logic.
|
||||
fn sapp_do_frame() {
|
||||
if g_sapp_state.first_frame {
|
||||
g_sapp_state.first_frame = false
|
||||
sapp_call_init()
|
||||
}
|
||||
sapp_call_frame()
|
||||
g_sapp_state.frame_count++
|
||||
}
|
||||
|
||||
// === Timing helpers ===
|
||||
|
||||
fn sapp_timing_reset(t &SappTiming) {
|
||||
unsafe {
|
||||
mut mt := t
|
||||
mt.last = 0.0
|
||||
mt.accum = 0.0
|
||||
mt.avg = 0.0
|
||||
mt.spike_count = 0
|
||||
mt.num = 0
|
||||
mt.ring_head = 0
|
||||
mt.ring_tail = 0
|
||||
}
|
||||
}
|
||||
|
||||
fn sapp_timing_get_avg(t &SappTiming) f64 {
|
||||
return t.avg
|
||||
}
|
||||
|
||||
// === Drop file helpers ===
|
||||
|
||||
fn sapp_dropped_file_path_ptr(index int) &char {
|
||||
assert g_sapp_state.drop.buffer != unsafe { nil }
|
||||
assert index >= 0 && index <= g_sapp_state.drop.max_files
|
||||
offset := index * g_sapp_state.drop.max_path_length
|
||||
assert offset < g_sapp_state.drop.buf_size
|
||||
return unsafe { &char(g_sapp_state.drop.buffer + offset) }
|
||||
}
|
||||
|
||||
// === State initialization ===
|
||||
|
||||
fn sapp_desc_defaults(desc &Desc) Desc {
|
||||
mut res := *desc
|
||||
if res.sample_count == 0 {
|
||||
res.sample_count = 1
|
||||
}
|
||||
if res.swap_interval == 0 {
|
||||
res.swap_interval = 1
|
||||
}
|
||||
if res.gl.major_version == 0 {
|
||||
res.gl.major_version = 4
|
||||
res.gl.minor_version = 1
|
||||
}
|
||||
if res.clipboard_size == 0 {
|
||||
res.clipboard_size = 8192
|
||||
}
|
||||
if res.max_dropped_files == 0 {
|
||||
res.max_dropped_files = 1
|
||||
}
|
||||
if res.max_dropped_file_path_length == 0 {
|
||||
res.max_dropped_file_path_length = 2048
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn sapp_init_state(desc &Desc) {
|
||||
unsafe { C.memset(&g_sapp_state, 0, int(sizeof(g_sapp_state))) }
|
||||
g_sapp_state.desc = sapp_desc_defaults(desc)
|
||||
g_sapp_state.first_frame = true
|
||||
g_sapp_state.window_width = g_sapp_state.desc.width
|
||||
g_sapp_state.window_height = g_sapp_state.desc.height
|
||||
g_sapp_state.framebuffer_width = g_sapp_state.window_width
|
||||
g_sapp_state.framebuffer_height = g_sapp_state.window_height
|
||||
g_sapp_state.sample_count = g_sapp_state.desc.sample_count
|
||||
g_sapp_state.swap_interval = g_sapp_state.desc.swap_interval
|
||||
g_sapp_state.clipboard.enabled = g_sapp_state.desc.enable_clipboard
|
||||
if g_sapp_state.clipboard.enabled {
|
||||
g_sapp_state.clipboard.buf_size = g_sapp_state.desc.clipboard_size
|
||||
g_sapp_state.clipboard.buffer = unsafe {
|
||||
&char(C.calloc(1, usize(g_sapp_state.clipboard.buf_size)))
|
||||
}
|
||||
}
|
||||
g_sapp_state.drop.enabled = g_sapp_state.desc.enable_dragndrop
|
||||
if g_sapp_state.drop.enabled {
|
||||
g_sapp_state.drop.max_files = g_sapp_state.desc.max_dropped_files
|
||||
g_sapp_state.drop.max_path_length = g_sapp_state.desc.max_dropped_file_path_length
|
||||
g_sapp_state.drop.buf_size = g_sapp_state.drop.max_files * g_sapp_state.drop.max_path_length
|
||||
g_sapp_state.drop.buffer = unsafe { &char(C.calloc(1, usize(g_sapp_state.drop.buf_size))) }
|
||||
}
|
||||
// Copy window title
|
||||
if g_sapp_state.desc.window_title != unsafe { nil }
|
||||
&& unsafe { C.strlen(g_sapp_state.desc.window_title) } > 0 {
|
||||
title := g_sapp_state.desc.window_title
|
||||
mut i := 0
|
||||
for i < max_title_length - 1 {
|
||||
ch := unsafe { title[i] }
|
||||
if ch == 0 {
|
||||
break
|
||||
}
|
||||
g_sapp_state.window_title[i] = u8(ch)
|
||||
i++
|
||||
}
|
||||
g_sapp_state.window_title[i] = 0
|
||||
} else {
|
||||
// Default title
|
||||
g_sapp_state.window_title[0] = `s`
|
||||
g_sapp_state.window_title[1] = `o`
|
||||
g_sapp_state.window_title[2] = `k`
|
||||
g_sapp_state.window_title[3] = `o`
|
||||
g_sapp_state.window_title[4] = `l`
|
||||
g_sapp_state.window_title[5] = 0
|
||||
}
|
||||
g_sapp_state.dpi_scale = 1.0
|
||||
g_sapp_state.fullscreen = g_sapp_state.desc.fullscreen
|
||||
g_sapp_state.mouse.shown = true
|
||||
}
|
||||
|
||||
fn sapp_discard_state() {
|
||||
if g_sapp_state.clipboard.enabled && g_sapp_state.clipboard.buffer != unsafe { nil } {
|
||||
unsafe { C.free(g_sapp_state.clipboard.buffer) }
|
||||
}
|
||||
if g_sapp_state.drop.enabled && g_sapp_state.drop.buffer != unsafe { nil } {
|
||||
unsafe { C.free(g_sapp_state.drop.buffer) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
module sapp
|
||||
|
||||
import sokol.memory
|
||||
|
||||
const max_touchpoints = 8
|
||||
const max_mousebuttons = 3
|
||||
const max_keycodes = 512
|
||||
const max_iconimages = 8
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_allocator {
|
||||
pub mut:
|
||||
alloc_fn memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free_fn memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
pub type Allocator = C.sapp_allocator
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_logger {
|
||||
pub mut:
|
||||
func memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
pub type Logger = C.sapp_logger
|
||||
|
||||
// sapp_range is a general pointer/size-pair struct for passing binary blobs into sokol_app.h
|
||||
@[typedef]
|
||||
pub struct C.sapp_range {
|
||||
pub:
|
||||
ptr voidptr
|
||||
size usize
|
||||
}
|
||||
|
||||
pub type Range = C.sapp_range
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_image_desc {
|
||||
pub:
|
||||
width int
|
||||
height int
|
||||
cursor_hotspot_x int
|
||||
cursor_hotspot_y int
|
||||
pixels Range
|
||||
}
|
||||
|
||||
pub type ImageDesc = C.sapp_image_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_icon_desc {
|
||||
pub:
|
||||
sokol_default bool
|
||||
images [max_iconimages]ImageDesc
|
||||
}
|
||||
|
||||
pub type IconDesc = C.sapp_icon_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_gl_desc {
|
||||
pub mut:
|
||||
major_version int // override GL/GLES major version
|
||||
minor_version int // override GL/GLES minor version
|
||||
}
|
||||
|
||||
pub type GlDesc = C.sapp_gl_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_win32_desc {
|
||||
pub:
|
||||
console_utf8 bool // if true, set the output console codepage to UTF-8
|
||||
console_create bool // if true, attach stdout/stderr to a new console window
|
||||
console_attach bool // if true, attach stdout/stderr to parent process
|
||||
}
|
||||
|
||||
pub type Win32Desc = C.sapp_win32_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_html5_desc {
|
||||
pub:
|
||||
canvas_selector &char = c'#canvas' // css selector of the HTML5 canvas element, default is "#canvas"
|
||||
canvas_resize bool // if true, the HTML5 canvas size is set to sapp_desc.width/height
|
||||
preserve_drawing_buffer bool // HTML5 only: whether to preserve default framebuffer content between frames
|
||||
premultiplied_alpha bool // HTML5 only: whether the rendered pixels use premultiplied alpha convention
|
||||
ask_leave_site bool // initial state of the internal html5_ask_leave_site flag
|
||||
update_document_title bool // if true, update the HTML document.title with sapp_desc.window_title
|
||||
bubble_mouse_events bool // if true, mouse events will bubble up to the web page
|
||||
bubble_touch_events bool // same for touch events
|
||||
bubble_wheel_events bool // same for wheel events
|
||||
bubble_key_events bool // if true, bubble up *all* key events to browser
|
||||
bubble_char_events bool // if true, bubble up character events to browser
|
||||
use_emsc_set_main_loop bool // if true, use emscripten_set_main_loop() instead of emscripten_request_animation_frame_loop()
|
||||
emsc_set_main_loop_simulate_infinite_loop bool // this will be passed as the simulate_infinite_loop arg to emscripten_set_main_loop()
|
||||
}
|
||||
|
||||
pub type Html5Desc = C.sapp_html5_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_ios_desc {
|
||||
pub:
|
||||
keyboard_resizes_canvas bool // if true, showing the iOS keyboard shrinks the canvas
|
||||
}
|
||||
|
||||
pub type IosDesc = C.sapp_ios_desc
|
||||
|
||||
// --- environment structs (returned by sapp_get_environment) ---
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_environment_defaults {
|
||||
pub:
|
||||
color_format int
|
||||
depth_format int
|
||||
sample_count int
|
||||
}
|
||||
|
||||
pub type EnvironmentDefaults = C.sapp_environment_defaults
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_metal_environment {
|
||||
pub:
|
||||
device voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_d3d11_environment {
|
||||
pub:
|
||||
device voidptr
|
||||
device_context voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_wgpu_environment {
|
||||
pub:
|
||||
device voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_vulkan_environment {
|
||||
pub:
|
||||
instance voidptr
|
||||
physical_device voidptr
|
||||
device voidptr
|
||||
queue voidptr
|
||||
queue_family_index u32
|
||||
}
|
||||
|
||||
pub type MetalEnvironment = C.sapp_metal_environment
|
||||
pub type D3d11Environment = C.sapp_d3d11_environment
|
||||
pub type WgpuEnvironment = C.sapp_wgpu_environment
|
||||
pub type VulkanEnvironment = C.sapp_vulkan_environment
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_environment {
|
||||
pub:
|
||||
defaults EnvironmentDefaults
|
||||
metal MetalEnvironment
|
||||
d3d11 D3d11Environment
|
||||
wgpu WgpuEnvironment
|
||||
vulkan VulkanEnvironment
|
||||
}
|
||||
|
||||
pub type Environment = C.sapp_environment
|
||||
|
||||
// --- swapchain structs (returned by sapp_get_swapchain) ---
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_metal_swapchain {
|
||||
pub:
|
||||
current_drawable voidptr
|
||||
depth_stencil_texture voidptr
|
||||
msaa_color_texture voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_d3d11_swapchain {
|
||||
pub:
|
||||
render_view voidptr
|
||||
resolve_view voidptr
|
||||
depth_stencil_view voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_wgpu_swapchain {
|
||||
pub:
|
||||
render_view voidptr
|
||||
resolve_view voidptr
|
||||
depth_stencil_view voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_vulkan_swapchain {
|
||||
pub:
|
||||
render_image voidptr
|
||||
render_view voidptr
|
||||
resolve_image voidptr
|
||||
resolve_view voidptr
|
||||
depth_stencil_image voidptr
|
||||
depth_stencil_view voidptr
|
||||
render_finished_semaphore voidptr
|
||||
present_complete_semaphore voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_gl_swapchain {
|
||||
pub:
|
||||
framebuffer u32
|
||||
}
|
||||
|
||||
pub type MetalSwapchain = C.sapp_metal_swapchain
|
||||
pub type D3d11Swapchain = C.sapp_d3d11_swapchain
|
||||
pub type WgpuSwapchain = C.sapp_wgpu_swapchain
|
||||
pub type VulkanSwapchain = C.sapp_vulkan_swapchain
|
||||
pub type GlSwapchain = C.sapp_gl_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_swapchain {
|
||||
pub:
|
||||
width int
|
||||
height int
|
||||
sample_count int
|
||||
color_format int
|
||||
depth_format int
|
||||
metal MetalSwapchain
|
||||
d3d11 D3d11Swapchain
|
||||
wgpu WgpuSwapchain
|
||||
vulkan VulkanSwapchain
|
||||
gl GlSwapchain
|
||||
}
|
||||
|
||||
pub type Swapchain = C.sapp_swapchain
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_desc {
|
||||
pub mut:
|
||||
// these are the user-provided callbacks without user data
|
||||
init_cb fn () = unsafe { nil }
|
||||
frame_cb fn () = unsafe { nil }
|
||||
cleanup_cb fn () = unsafe { nil }
|
||||
event_cb fn (&Event) = unsafe { nil } // &sapp_event
|
||||
|
||||
user_data voidptr // these are the user-provided callbacks with user data
|
||||
init_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
frame_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
cleanup_userdata_cb fn (voidptr) = unsafe { nil }
|
||||
event_userdata_cb fn (&Event, voidptr) = unsafe { nil }
|
||||
|
||||
width int // the preferred width of the window / canvas
|
||||
height int // the preferred height of the window / canvas
|
||||
sample_count int // MSAA sample count
|
||||
swap_interval int // the preferred swap interval on Windows, macOS, Linux, iOS, and HTML5; Android support is not implemented yet
|
||||
high_dpi bool // whether the rendering canvas is full-resolution on HighDPI displays
|
||||
fullscreen bool // whether the window should be created in fullscreen mode
|
||||
alpha bool // whether the framebuffer should have an alpha channel (ignored on some platforms)
|
||||
window_title &char // the window title as UTF-8 encoded string
|
||||
enable_clipboard bool // enable clipboard access, default is false
|
||||
clipboard_size int // max size of clipboard content in bytes
|
||||
enable_dragndrop bool // enable file dropping (drag'n'drop), default is false
|
||||
max_dropped_files int // max number of dropped files to process (default: 1)
|
||||
max_dropped_file_path_length int // max length in bytes of a dropped UTF-8 file path (default: 2048)
|
||||
icon IconDesc // the initial window icon to set
|
||||
allocator Allocator // optional memory allocation overrides (default: malloc/free)
|
||||
logger Logger // logging callback override (default: NO LOGGING!)
|
||||
// backend-specific options
|
||||
gl GlDesc // OpenGL specific options
|
||||
win32 Win32Desc // Win32 specific options
|
||||
html5 Html5Desc // HTML5 specific options
|
||||
ios IosDesc // iOS specific options
|
||||
// V patches
|
||||
__v_native_render bool // V patch to allow for native rendering
|
||||
min_width int // V patch to allow for min window width
|
||||
min_height int // V patch to allow for min window height
|
||||
borderless_window bool // V patch to create a window without native decorations when supported
|
||||
}
|
||||
|
||||
pub type Desc = C.sapp_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_event {
|
||||
pub mut:
|
||||
frame_count u64 // current frame counter, always valid, useful for checking if two events were issued in the same frame
|
||||
type EventType // the event type, always valid
|
||||
key_code KeyCode // the virtual key code, only valid in KEY_UP, KEY_DOWN
|
||||
char_code u32 // the UTF-32 character code, only valid in CHAR events
|
||||
key_repeat bool // true if this is a key-repeat event, valid in KEY_UP, KEY_DOWN and CHAR
|
||||
modifiers u32 // current modifier keys, valid in all key-, char- and mouse-events
|
||||
mouse_button MouseButton // mouse button that was pressed or released, valid in MOUSE_DOWN, MOUSE_UP
|
||||
mouse_x f32 // current horizontal mouse position in pixels, always valid except during mouse lock
|
||||
mouse_y f32 // current vertical mouse position in pixels, always valid except during mouse lock
|
||||
mouse_dx f32 // relative horizontal mouse movement since last frame, always valid
|
||||
mouse_dy f32 // relative vertical mouse movement since last frame, always valid
|
||||
scroll_x f32 // horizontal mouse wheel scroll distance, valid in MOUSE_SCROLL events
|
||||
scroll_y f32 // vertical mouse wheel scroll distance, valid in MOUSE_SCROLL events
|
||||
num_touches int // number of valid items in the touches[] array
|
||||
touches [max_touchpoints]TouchPoint // current touch points, valid in TOUCHES_BEGIN, TOUCHES_MOVED, TOUCHES_ENDED
|
||||
window_width int // current window- and framebuffer width in pixels, always valid
|
||||
window_height int // current window- and framebuffer height in pixels, always valid
|
||||
framebuffer_width int // = window_width * dpi_scale
|
||||
framebuffer_height int // = window_height * dpi_scale
|
||||
}
|
||||
|
||||
pub type Event = C.sapp_event
|
||||
|
||||
pub fn (e &Event) str() string {
|
||||
return 'evt: frame_count=${e.frame_count}, type=${EventType(e.type)}'
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_touchpoint {
|
||||
pub:
|
||||
identifier u64
|
||||
pos_x f32
|
||||
pos_y f32
|
||||
android_tooltype TouchToolType
|
||||
changed bool
|
||||
}
|
||||
|
||||
pub type TouchPoint = C.sapp_touchpoint
|
||||
@@ -0,0 +1,69 @@
|
||||
module sapp
|
||||
|
||||
import os
|
||||
import stbi
|
||||
|
||||
#define SOKOL_VALIDATE_NON_FATAL 1
|
||||
|
||||
// v_sapp_gl_read_rgba_pixels reads pixles from the OpenGL buffer into `pixels`.
|
||||
fn C.v_sapp_gl_read_rgba_pixels(x int, y int, width int, height int, pixels charptr)
|
||||
|
||||
// screenshot takes a screenshot of the current window and
|
||||
// saves it to `path`. The format is inferred from the extension
|
||||
// of the file name in `path`.
|
||||
//
|
||||
// Supported formats are: `.png`, `.ppm`.
|
||||
pub fn screenshot(path string) ! {
|
||||
match os.file_ext(path) {
|
||||
'.png' {
|
||||
return screenshot_png(path)
|
||||
}
|
||||
'.ppm' {
|
||||
return screenshot_ppm(path)
|
||||
}
|
||||
else {
|
||||
return error(@MOD + '.' + @FN + ' currently only supports .png and .ppm files.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// screenshot_ppm takes a screenshot of the current window and
|
||||
// saves it to `path` as a .ppm file.
|
||||
@[manualfree]
|
||||
pub fn screenshot_ppm(path string) ! {
|
||||
ss := screenshot_window()
|
||||
write_rgba_to_ppm(path, ss.width, ss.height, 4, ss.pixels)!
|
||||
unsafe { ss.destroy() }
|
||||
}
|
||||
|
||||
// screenshot_png takes a screenshot of the current window and
|
||||
// saves it to `path` as a .png file.
|
||||
@[manualfree]
|
||||
pub fn screenshot_png(path string) ! {
|
||||
ss := screenshot_window()
|
||||
stbi.set_flip_vertically_on_write(true)
|
||||
stbi.stbi_write_png(path, ss.width, ss.height, 4, ss.pixels, ss.width * 4)!
|
||||
unsafe { ss.destroy() }
|
||||
}
|
||||
|
||||
// write_rgba_to_ppm writes `pixels` data in RGBA format to PPM3 format.
|
||||
fn write_rgba_to_ppm(path string, w int, h int, components int, pixels &u8) ! {
|
||||
mut f_out := os.create(path)!
|
||||
defer {
|
||||
f_out.close()
|
||||
}
|
||||
f_out.writeln('P3')!
|
||||
f_out.writeln('${w} ${h}')!
|
||||
f_out.writeln('255')!
|
||||
for i := h - 1; i >= 0; i-- {
|
||||
for j := 0; j < w; j++ {
|
||||
idx := i * w * components + j * components
|
||||
unsafe {
|
||||
r := int(pixels[idx])
|
||||
g := int(pixels[idx + 1])
|
||||
b := int(pixels[idx + 2])
|
||||
f_out.write_string('${r} ${g} ${b} ')!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,42 @@
|
||||
module sapp
|
||||
|
||||
@[heap]
|
||||
pub struct Screenshot {
|
||||
width int
|
||||
height int
|
||||
size int
|
||||
mut:
|
||||
pixels &u8 = unsafe { nil }
|
||||
}
|
||||
|
||||
@[manualfree]
|
||||
pub fn screenshot_window() &Screenshot {
|
||||
img_width := width()
|
||||
img_height := height()
|
||||
img_size := img_width * img_height * 4
|
||||
img_pixels := unsafe { &u8(malloc(img_size)) }
|
||||
C.v_sapp_gl_read_rgba_pixels(0, 0, img_width, img_height, img_pixels)
|
||||
return &Screenshot{
|
||||
width: img_width
|
||||
height: img_height
|
||||
size: img_size
|
||||
pixels: img_pixels
|
||||
}
|
||||
}
|
||||
|
||||
// free - free *only* the Screenshot pixels.
|
||||
@[unsafe]
|
||||
pub fn (mut ss Screenshot) free() {
|
||||
unsafe {
|
||||
free(ss.pixels)
|
||||
ss.pixels = &u8(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// destroy - free the Screenshot pixels,
|
||||
// then free the screenshot data structure itself.
|
||||
@[unsafe]
|
||||
pub fn (mut ss Screenshot) destroy() {
|
||||
unsafe { ss.free() }
|
||||
unsafe { free(ss) }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
module sfons
|
||||
|
||||
import fontstash
|
||||
import sokol.f as _
|
||||
import sokol.memory
|
||||
|
||||
// create a new Context/font atlas, for rendering glyphs, given its dimensions `width` and `height`
|
||||
@[inline]
|
||||
pub fn create(width int, height int, flags int) &fontstash.Context {
|
||||
assert is_power_of_two(width)
|
||||
assert is_power_of_two(height)
|
||||
allocator := C.sfons_allocator_t{
|
||||
alloc_fn: memory.salloc
|
||||
free_fn: memory.sfree
|
||||
user_data: voidptr(0x100005f0)
|
||||
}
|
||||
desc := C.sfons_desc_t{
|
||||
width: width
|
||||
height: height
|
||||
allocator: allocator
|
||||
}
|
||||
return C.sfons_create(&desc)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy(ctx &fontstash.Context) {
|
||||
C.sfons_destroy(ctx)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn rgba(r u8, g u8, b u8, a u8) u32 {
|
||||
return C.sfons_rgba(r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn flush(ctx &fontstash.Context) {
|
||||
C.sfons_flush(ctx)
|
||||
}
|
||||
|
||||
fn is_power_of_two(x int) bool {
|
||||
return x in [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
module sfons
|
||||
|
||||
import fontstash
|
||||
import sokol.memory
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sfons_allocator_t {
|
||||
pub:
|
||||
alloc_fn memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free_fn memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sfons_desc_t {
|
||||
pub:
|
||||
width int // initial width of font atlas texture (default: 512, must be power of 2)
|
||||
height int // initial height of font atlas texture (default: 512, must be power of 2)
|
||||
allocator C.sfons_allocator_t // optional memory allocation overrides
|
||||
}
|
||||
|
||||
fn C.sfons_create(const_desc &C.sfons_desc_t) &fontstash.Context
|
||||
fn C.sfons_destroy(ctx &fontstash.Context)
|
||||
fn C.sfons_flush(ctx &fontstash.Context)
|
||||
|
||||
fn C.sfons_rgba(r u8, g u8, b u8, a u8) u32
|
||||
@@ -0,0 +1,12 @@
|
||||
module sgl
|
||||
|
||||
// SglError is C.sgl_error_t
|
||||
pub enum SglError {
|
||||
no_error = C.SGL_NO_ERROR // 0
|
||||
vertices_full = C.SGL_ERROR_VERTICES_FULL
|
||||
uniforms_full = C.SGL_ERROR_UNIFORMS_FULL
|
||||
commands_full = C.SGL_ERROR_COMMANDS_FULL
|
||||
stack_overflow = C.SGL_ERROR_STACK_OVERFLOW
|
||||
stack_underflow = C.SGL_ERROR_STACK_UNDERFLOW
|
||||
no_context = C.SGL_ERROR_NO_CONTEXT
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
module sgl
|
||||
|
||||
import sokol.gfx
|
||||
import sokol.memory
|
||||
|
||||
pub const version = gfx.version + 1
|
||||
|
||||
pub const context = Context{0x00010001} // C.SGL_DEFAULT_CONTEXT = { 0x00010001 }
|
||||
|
||||
// setup/shutdown/misc
|
||||
pub fn setup(desc &Desc) {
|
||||
if desc.allocator.alloc_fn == unsafe { nil } && desc.allocator.free_fn == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.allocator.alloc_fn = memory.salloc
|
||||
desc.allocator.free_fn = memory.sfree
|
||||
desc.allocator.user_data = voidptr(0x10000561)
|
||||
}
|
||||
}
|
||||
if desc.logger.func == unsafe { nil } {
|
||||
unsafe {
|
||||
desc.logger.func = memory.slog
|
||||
}
|
||||
}
|
||||
C.sgl_setup(desc)
|
||||
}
|
||||
|
||||
pub fn shutdown() {
|
||||
C.sgl_shutdown()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn error() SglError {
|
||||
return unsafe { SglError(int(C.sgl_error())) }
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn context_error(ctx Context) SglError {
|
||||
return unsafe { SglError(int(C.sgl_context_error(ctx))) }
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn rad(deg f32) f32 {
|
||||
return C.sgl_rad(deg)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn deg(rad f32) f32 {
|
||||
return C.sgl_deg(rad)
|
||||
}
|
||||
|
||||
// context functions
|
||||
@[inline]
|
||||
pub fn make_context(desc &ContextDesc) Context {
|
||||
return C.sgl_make_context(desc)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_context(ctx Context) {
|
||||
C.sgl_destroy_context(ctx)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn set_context(ctx Context) {
|
||||
C.sgl_set_context(ctx)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn get_context() Context {
|
||||
return C.sgl_get_context()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn default_context() Context {
|
||||
return C.sgl_default_context()
|
||||
}
|
||||
|
||||
// create and destroy pipeline objects
|
||||
@[inline]
|
||||
pub fn make_pipeline(desc &gfx.PipelineDesc) Pipeline {
|
||||
return C.sgl_make_pipeline(desc)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn context_make_pipeline(ctx Context, desc &gfx.PipelineDesc) Pipeline {
|
||||
return C.sgl_context_make_pipeline(ctx, desc)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn destroy_pipeline(pip Pipeline) {
|
||||
C.sgl_destroy_pipeline(pip)
|
||||
}
|
||||
|
||||
// render state functions
|
||||
@[inline]
|
||||
pub fn defaults() {
|
||||
C.sgl_defaults()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn viewport(x int, y int, w int, h int, origin_top_left bool) {
|
||||
C.sgl_viewport(x, y, w, h, origin_top_left)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn scissor_rect(x int, y int, w int, h int, origin_top_left bool) {
|
||||
C.sgl_scissor_rect(x, y, w, h, origin_top_left)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn scissor_rectf(x f32, y f32, w f32, h f32, origin_top_left bool) {
|
||||
C.sgl_scissor_rectf(x, y, w, h, origin_top_left)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn enable_texture() {
|
||||
C.sgl_enable_texture()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn disable_texture() {
|
||||
C.sgl_disable_texture()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn texture(img gfx.Image, smp gfx.Sampler) {
|
||||
C.sgl_texture(img, smp)
|
||||
}
|
||||
|
||||
// pipeline stack functions
|
||||
@[inline]
|
||||
pub fn load_default_pipeline() {
|
||||
C.sgl_load_default_pipeline()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn default_pipeline() {
|
||||
C.sgl_load_default_pipeline()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn load_pipeline(pip Pipeline) {
|
||||
C.sgl_load_pipeline(pip)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn push_pipeline() {
|
||||
C.sgl_push_pipeline()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn pop_pipeline() {
|
||||
C.sgl_pop_pipeline()
|
||||
}
|
||||
|
||||
// matrix stack functions
|
||||
@[inline]
|
||||
pub fn matrix_mode_modelview() {
|
||||
C.sgl_matrix_mode_modelview()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn matrix_mode_projection() {
|
||||
C.sgl_matrix_mode_projection()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn matrix_mode_texture() {
|
||||
C.sgl_matrix_mode_texture()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn load_identity() {
|
||||
C.sgl_load_identity()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn load_matrix(m []f32) {
|
||||
C.sgl_load_matrix(m.data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn load_transpose_matrix(m []f32) {
|
||||
C.sgl_load_transpose_matrix(m.data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn mult_matrix(m []f32) {
|
||||
C.sgl_mult_matrix(m.data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn mult_transpose_matrix(m []f32) {
|
||||
C.sgl_mult_transpose_matrix(m.data)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn rotate(angle_rad f32, x f32, y f32, z f32) {
|
||||
C.sgl_rotate(angle_rad, x, y, z)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn scale(x f32, y f32, z f32) {
|
||||
C.sgl_scale(x, y, z)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn translate(x f32, y f32, z f32) {
|
||||
C.sgl_translate(x, y, z)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn frustum(l f32, r f32, b f32, t f32, n f32, f f32) {
|
||||
C.sgl_frustum(l, r, b, t, n, f)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn ortho(l f32, r f32, b f32, t f32, n f32, f f32) {
|
||||
C.sgl_ortho(l, r, b, t, n, f)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn perspective(fov_y f32, aspect f32, z_near f32, z_far f32) {
|
||||
C.sgl_perspective(fov_y, aspect, z_near, z_far)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn lookat(eye_x f32, eye_y f32, eye_z f32, center_x f32, center_y f32, center_z f32, up_x f32, up_y f32,
|
||||
up_z f32) {
|
||||
C.sgl_lookat(eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, up_y, up_z)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn push_matrix() {
|
||||
C.sgl_push_matrix()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn pop_matrix() {
|
||||
C.sgl_pop_matrix()
|
||||
}
|
||||
|
||||
// these functions only set the internal 'current texcoord / color' (valid inside or outside begin/end)
|
||||
@[inline]
|
||||
pub fn t2f(u f32, v f32) {
|
||||
C.sgl_t2f(u, v)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn c3f(r f32, g f32, b f32) {
|
||||
C.sgl_c3f(r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn c4f(r f32, g f32, b f32, a f32) {
|
||||
C.sgl_c4f(r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn c3b(r u8, g u8, b u8) {
|
||||
C.sgl_c3b(r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn c4b(r u8, g u8, b u8, a u8) {
|
||||
C.sgl_c4b(r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn c1i(rgba u32) {
|
||||
C.sgl_c1i(rgba)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn point_size(s f32) {
|
||||
C.sgl_point_size(s)
|
||||
}
|
||||
|
||||
// define primitives, each begin/end is one draw command
|
||||
@[inline]
|
||||
pub fn begin_points() {
|
||||
C.sgl_begin_points()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn begin_lines() {
|
||||
C.sgl_begin_lines()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn begin_line_strip() {
|
||||
C.sgl_begin_line_strip()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn begin_triangles() {
|
||||
C.sgl_begin_triangles()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn begin_triangle_strip() {
|
||||
C.sgl_begin_triangle_strip()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn begin_quads() {
|
||||
C.sgl_begin_quads()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f(x f32, y f32) {
|
||||
C.sgl_v2f(x, y)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f(x f32, y f32, z f32) {
|
||||
C.sgl_v3f(x, y, z)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f(x f32, y f32, u f32, v f32) {
|
||||
C.sgl_v2f_t2f(x, y, u, v)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f(x f32, y f32, z f32, u f32, v f32) {
|
||||
C.sgl_v3f_t2f(x, y, z, u, v)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_c3f(x f32, y f32, r f32, g f32, b f32) {
|
||||
C.sgl_v2f_c3f(x, y, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_c3b(x f32, y f32, r u8, g u8, b u8) {
|
||||
C.sgl_v2f_c3b(x, y, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_c4f(x f32, y f32, r f32, g f32, b f32, a f32) {
|
||||
C.sgl_v2f_c4f(x, y, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_c4b(x f32, y f32, r u8, g u8, b u8, a u8) {
|
||||
C.sgl_v2f_c4b(x, y, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_c1i(x f32, y f32, rgba u32) {
|
||||
C.sgl_v2f_c1i(x, y, rgba)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_c3f(x f32, y f32, z f32, r f32, g f32, b f32) {
|
||||
C.sgl_v3f_c3f(x, y, z, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_c3b(x f32, y f32, z f32, r u8, g u8, b u8) {
|
||||
C.sgl_v3f_c3b(x, y, z, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_c4f(x f32, y f32, z f32, r f32, g f32, b f32, a f32) {
|
||||
C.sgl_v3f_c4f(x, y, z, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_c4b(x f32, y f32, z f32, r u8, g u8, b u8, a u8) {
|
||||
C.sgl_v3f_c4b(x, y, z, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_c1i(x f32, y f32, z f32, rgba u32) {
|
||||
C.sgl_v3f_c1i(x, y, z, rgba)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f_c3f(x f32, y f32, u f32, v f32, r f32, g f32, b f32) {
|
||||
C.sgl_v2f_t2f_c3f(x, y, u, v, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f_c3b(x f32, y f32, u f32, v f32, r u8, g u8, b u8) {
|
||||
C.sgl_v2f_t2f_c3b(x, y, u, v, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f_c4f(x f32, y f32, u f32, v f32, r f32, g f32, b f32, a f32) {
|
||||
C.sgl_v2f_t2f_c4f(x, y, u, v, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f_c4b(x f32, y f32, u f32, v f32, r u8, g u8, b u8, a u8) {
|
||||
C.sgl_v2f_t2f_c4b(x, y, u, v, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v2f_t2f_c1i(x f32, y f32, u f32, v f32, rgba u32) {
|
||||
C.sgl_v2f_t2f_c1i(x, y, u, v, rgba)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f_c3f(x f32, y f32, z f32, u f32, v f32, r f32, g f32, b f32) {
|
||||
C.sgl_v3f_t2f_c3f(x, y, z, u, v, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f_c3b(x f32, y f32, z f32, u f32, v f32, r u8, g u8, b u8) {
|
||||
C.sgl_v3f_t2f_c3b(x, y, z, u, v, r, g, b)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f_c4f(x f32, y f32, z f32, u f32, v f32, r f32, g f32, b f32, a f32) {
|
||||
C.sgl_v3f_t2f_c4f(x, y, z, u, v, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f_c4b(x f32, y f32, z f32, u f32, v f32, r u8, g u8, b u8, a u8) {
|
||||
C.sgl_v3f_t2f_c4b(x, y, z, u, v, r, g, b, a)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn v3f_t2f_c1i(x f32, y f32, z f32, u f32, v f32, rgba u32) {
|
||||
C.sgl_v3f_t2f_c1i(x, y, z, u, v, rgba)
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn end() {
|
||||
C.sgl_end()
|
||||
}
|
||||
|
||||
// render recorded commands
|
||||
@[inline]
|
||||
pub fn draw() {
|
||||
C.sgl_draw()
|
||||
}
|
||||
|
||||
@[inline]
|
||||
pub fn context_draw(ctx Context) {
|
||||
C.sgl_context_draw(ctx)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
module sgl
|
||||
|
||||
import sokol.memory
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_allocator_t {
|
||||
pub mut:
|
||||
alloc_fn memory.FnAllocatorAlloc = unsafe { nil }
|
||||
free_fn memory.FnAllocatorFree = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_logger_t {
|
||||
pub mut:
|
||||
func memory.FnLogCb = unsafe { nil }
|
||||
user_data voidptr
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
module sgl
|
||||
|
||||
// setup/shutdown/misc
|
||||
fn C.sgl_setup(const_desc &C.sgl_desc_t)
|
||||
fn C.sgl_shutdown()
|
||||
fn C.sgl_error() SglError
|
||||
fn C.sgl_context_error(ctx C.sgl_context) SglError
|
||||
fn C.sgl_rad(deg f32) f32
|
||||
fn C.sgl_deg(rad f32) f32
|
||||
|
||||
// context functions
|
||||
fn C.sgl_make_context(const_desc &C.sgl_context_desc_t) C.sgl_context
|
||||
fn C.sgl_destroy_context(ctx C.sgl_context)
|
||||
fn C.sgl_set_context(ctx C.sgl_context)
|
||||
fn C.sgl_get_context() C.sgl_context
|
||||
fn C.sgl_default_context() C.sgl_context
|
||||
|
||||
// create and destroy pipeline objects
|
||||
fn C.sgl_make_pipeline(const_desc &C.sg_pipeline_desc) C.sgl_pipeline
|
||||
fn C.sgl_context_make_pipeline(ctx C.sgl_context, const_desc &C.sg_pipeline_desc) C.sgl_pipeline
|
||||
fn C.sgl_destroy_pipeline(pip C.sgl_pipeline)
|
||||
|
||||
// render state functions
|
||||
fn C.sgl_defaults()
|
||||
fn C.sgl_viewport(x int, y int, w int, h int, origin_top_left bool)
|
||||
fn C.sgl_viewportf(x f32, y f32, w f32, h f32, origin_top_left bool)
|
||||
fn C.sgl_scissor_rect(x int, y int, w int, h int, origin_top_left bool)
|
||||
fn C.sgl_scissor_rectf(x f32, y f32, w f32, h f32, origin_top_left bool)
|
||||
fn C.sgl_enable_texture()
|
||||
fn C.sgl_disable_texture()
|
||||
fn C.sgl_texture(img C.sg_image, sampler C.sg_sampler)
|
||||
|
||||
// pipeline stack functions
|
||||
fn C.sgl_load_default_pipeline()
|
||||
fn C.sgl_load_pipeline(pip C.sgl_pipeline)
|
||||
fn C.sgl_push_pipeline()
|
||||
fn C.sgl_pop_pipeline()
|
||||
|
||||
// matrix stack functions
|
||||
fn C.sgl_matrix_mode_modelview()
|
||||
fn C.sgl_matrix_mode_projection()
|
||||
fn C.sgl_matrix_mode_texture()
|
||||
fn C.sgl_load_identity()
|
||||
fn C.sgl_load_matrix(m [16]f32)
|
||||
fn C.sgl_load_transpose_matrix(m [16]f32)
|
||||
fn C.sgl_mult_matrix(m [16]f32)
|
||||
fn C.sgl_mult_transpose_matrix(m [16]f32)
|
||||
fn C.sgl_rotate(angle_rad f32, x f32, y f32, z f32)
|
||||
fn C.sgl_scale(x f32, y f32, z f32)
|
||||
fn C.sgl_translate(x f32, y f32, z f32)
|
||||
fn C.sgl_frustum(l f32, r f32, b f32, t f32, n f32, f f32)
|
||||
fn C.sgl_ortho(l f32, r f32, b f32, t f32, n f32, f f32)
|
||||
fn C.sgl_perspective(fov_y f32, aspect f32, z_near f32, z_far f32)
|
||||
fn C.sgl_lookat(eye_x f32, eye_y f32, eye_z f32, center_x f32, center_y f32, center_z f32, up_x f32, up_y f32,
|
||||
up_z f32)
|
||||
fn C.sgl_push_matrix()
|
||||
fn C.sgl_pop_matrix()
|
||||
|
||||
// these functions only set the internal 'current texcoord / color' (valid inside or outside begin/end)
|
||||
fn C.sgl_t2f(u f32, v f32)
|
||||
fn C.sgl_c3f(r f32, g f32, b f32)
|
||||
fn C.sgl_c4f(r f32, g f32, b f32, a f32)
|
||||
fn C.sgl_c3b(r u8, g u8, b u8)
|
||||
fn C.sgl_c4b(r u8, g u8, b u8, a u8)
|
||||
fn C.sgl_c1i(rgba u32)
|
||||
fn C.sgl_point_size(s f32)
|
||||
|
||||
// define primitives, each begin/end is one draw command
|
||||
fn C.sgl_begin_points()
|
||||
fn C.sgl_begin_lines()
|
||||
fn C.sgl_begin_line_strip()
|
||||
fn C.sgl_begin_triangles()
|
||||
fn C.sgl_begin_triangle_strip()
|
||||
fn C.sgl_begin_quads()
|
||||
fn C.sgl_v2f(x f32, y f32)
|
||||
fn C.sgl_v3f(x f32, y f32, z f32)
|
||||
fn C.sgl_v2f_t2f(x f32, y f32, u f32, v f32)
|
||||
fn C.sgl_v3f_t2f(x f32, y f32, z f32, u f32, v f32)
|
||||
fn C.sgl_v2f_c3f(x f32, y f32, r f32, g f32, b f32)
|
||||
fn C.sgl_v2f_c3b(x f32, y f32, r u8, g u8, b u8)
|
||||
fn C.sgl_v2f_c4f(x f32, y f32, r f32, g f32, b f32, a f32)
|
||||
fn C.sgl_v2f_c4b(x f32, y f32, r u8, g u8, b u8, a u8)
|
||||
fn C.sgl_v2f_c1i(x f32, y f32, rgba u32)
|
||||
fn C.sgl_v3f_c3f(x f32, y f32, z f32, r f32, g f32, b f32)
|
||||
fn C.sgl_v3f_c3b(x f32, y f32, z f32, r u8, g u8, b u8)
|
||||
fn C.sgl_v3f_c4f(x f32, y f32, z f32, r f32, g f32, b f32, a f32)
|
||||
fn C.sgl_v3f_c4b(x f32, y f32, z f32, r u8, g u8, b u8, a u8)
|
||||
fn C.sgl_v3f_c1i(x f32, y f32, z f32, rgba u32)
|
||||
fn C.sgl_v2f_t2f_c3f(x f32, y f32, u f32, v f32, r f32, g f32, b f32)
|
||||
fn C.sgl_v2f_t2f_c3b(x f32, y f32, u f32, v f32, r u8, g u8, b u8)
|
||||
fn C.sgl_v2f_t2f_c4f(x f32, y f32, u f32, v f32, r f32, g f32, b f32, a f32)
|
||||
fn C.sgl_v2f_t2f_c4b(x f32, y f32, u f32, v f32, r u8, g u8, b u8, a u8)
|
||||
fn C.sgl_v2f_t2f_c1i(x f32, y f32, u f32, v f32, rgba u32)
|
||||
fn C.sgl_v3f_t2f_c3f(x f32, y f32, z f32, u f32, v f32, r f32, g f32, b f32)
|
||||
fn C.sgl_v3f_t2f_c3b(x f32, y f32, z f32, u f32, v f32, r u8, g u8, b u8)
|
||||
fn C.sgl_v3f_t2f_c4f(x f32, y f32, z f32, u f32, v f32, r f32, g f32, b f32, a f32)
|
||||
fn C.sgl_v3f_t2f_c4b(x f32, y f32, z f32, u f32, v f32, r u8, g u8, b u8, a u8)
|
||||
fn C.sgl_v3f_t2f_c1i(x f32, y f32, z f32, u f32, v f32, rgba u32)
|
||||
fn C.sgl_end()
|
||||
|
||||
// render recorded commands
|
||||
fn C.sgl_draw()
|
||||
fn C.sgl_context_draw(ctx C.sgl_context)
|
||||
@@ -0,0 +1,52 @@
|
||||
module sgl
|
||||
|
||||
import sokol.gfx
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_pipeline {
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Pipeline = C.sgl_pipeline
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_context {
|
||||
id u32
|
||||
}
|
||||
|
||||
pub type Context = C.sgl_context
|
||||
|
||||
// ContextDesc
|
||||
//
|
||||
// Describes the initialization parameters of a rendering context.
|
||||
// Creating additional contexts is useful if you want to render
|
||||
// in separate sokol-gfx passes.
|
||||
// ContextDesc is sgl_context_desc_t
|
||||
pub type ContextDesc = C.sgl_context_desc_t
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_context_desc_t {
|
||||
max_vertices int // default: 64k
|
||||
max_commands int // default: 16k
|
||||
color_format gfx.PixelFormat // C.sg_pixel_format
|
||||
depth_format gfx.PixelFormat // C.sg_pixel_format
|
||||
sample_count int
|
||||
}
|
||||
|
||||
pub type Desc = C.sgl_desc_t
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sgl_desc_t {
|
||||
pub:
|
||||
max_vertices int // size for vertex buffer
|
||||
max_commands int // size of uniform- and command-buffers
|
||||
context_pool_size int // max number of contexts (including default context), default: 4
|
||||
pipeline_pool_size int // size of internal pipeline pool, default: 64
|
||||
color_format gfx.PixelFormat // C.sg_pixel_format
|
||||
depth_format gfx.PixelFormat // C.sg_pixel_format
|
||||
sample_count int
|
||||
face_winding gfx.FaceWinding // C.sg_face_winding // default front face winding is CCW
|
||||
pub mut:
|
||||
allocator C.sgl_allocator_t // optional memory allocation overrides (default: malloc/free)
|
||||
logger C.sgl_logger_t // optional memory allocation overrides (default: SOKOL_LOG(message))
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
module sokol
|
||||
|
||||
import sokol.c as _
|
||||
|
||||
/* pub enum Key {
|
||||
up = C.SAPP_KEYCODE_UP
|
||||
left = C.SAPP_KEYCODE_LEFT
|
||||
right = C.SAPP_KEYCODE_RIGHT
|
||||
down = C.SAPP_KEYCODE_DOWN
|
||||
escape = C.SAPP_KEYCODE_ESCAPE
|
||||
space = C.SAPP_KEYCODE_SPACE
|
||||
} */
|
||||
Reference in new issue
Block a user