From 227dbc7d4a3943fe8f1541f595b6ef9851bef552 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 6 Apr 2026 20:42:14 +0300 Subject: [PATCH] sokol: remove duplicate types --- vlib/sokol/c/declaration.c.v | 4 + vlib/sokol/f/f.v | 12 + vlib/sokol/sapp/{enums.v => enums.c.v} | 38 +- vlib/sokol/sapp/{sapp.v => sapp.c.v} | 152 +- vlib/sokol/sapp/sapp_allocator_and_logger.c.v | 18 + vlib/sokol/sapp/{sapp_v.v => sapp_v.c.v} | 6 +- .../sapp/{screenshot.v => screenshot.c.v} | 1 - vlib/sokol/sfons/sfons.c.v | 42 + vlib/sokol/sfons/sfons.v | 388 ---- vlib/sokol/sfons/sfons_funcs.c.v | 26 + vlib/sokol/sgl/enums.c.v | 12 + vlib/sokol/sgl/enums.v | 36 - vlib/sokol/sgl/matrix.v | 242 --- vlib/sokol/sgl/sgl.c.v | 443 +++++ vlib/sokol/sgl/sgl.v | 1676 ----------------- vlib/sokol/sgl/sgl_allocator_and_logger.c.v | 18 + vlib/sokol/sgl/sgl_funcs.c.v | 103 + vlib/sokol/sgl/sgl_structs.c.v | 52 + vlib/sokol/sgl/sgl_structs.v | 222 --- vlib/sokol/sgl/shaders.v | 180 -- vlib/v/checker/checker.v | 2 +- vlib/v/gen/c/autofree.v | 2 +- vlib/v/gen/c/str_intp.v | 2 +- vlib/v/markused/walker.v | 3 + .../generics_map_with_reference_arg_test.v | 4 +- 25 files changed, 769 insertions(+), 2915 deletions(-) create mode 100644 vlib/sokol/f/f.v rename vlib/sokol/sapp/{enums.v => enums.c.v} (87%) rename vlib/sokol/sapp/{sapp.v => sapp.c.v} (60%) create mode 100644 vlib/sokol/sapp/sapp_allocator_and_logger.c.v rename vlib/sokol/sapp/{sapp_v.v => sapp_v.c.v} (88%) rename vlib/sokol/sapp/{screenshot.v => screenshot.c.v} (92%) create mode 100644 vlib/sokol/sfons/sfons.c.v delete mode 100644 vlib/sokol/sfons/sfons.v create mode 100644 vlib/sokol/sfons/sfons_funcs.c.v create mode 100644 vlib/sokol/sgl/enums.c.v delete mode 100644 vlib/sokol/sgl/enums.v delete mode 100644 vlib/sokol/sgl/matrix.v create mode 100644 vlib/sokol/sgl/sgl.c.v delete mode 100644 vlib/sokol/sgl/sgl.v create mode 100644 vlib/sokol/sgl/sgl_allocator_and_logger.c.v create mode 100644 vlib/sokol/sgl/sgl_funcs.c.v create mode 100644 vlib/sokol/sgl/sgl_structs.c.v delete mode 100644 vlib/sokol/sgl/sgl_structs.v delete mode 100644 vlib/sokol/sgl/shaders.v diff --git a/vlib/sokol/c/declaration.c.v b/vlib/sokol/c/declaration.c.v index cc169cf5c..ce850acbc 100644 --- a/vlib/sokol/c/declaration.c.v +++ b/vlib/sokol/c/declaration.c.v @@ -117,4 +117,8 @@ $if !no_sokol_app ? { #define SOKOL_NO_DEPRECATED #include "sokol_gfx.h" +@[use_once] +#define SOKOL_IMPL +#include "util/sokol_gl.h" + #include "sokol_v.post.h" diff --git a/vlib/sokol/f/f.v b/vlib/sokol/f/f.v new file mode 100644 index 000000000..1a096728c --- /dev/null +++ b/vlib/sokol/f/f.v @@ -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" diff --git a/vlib/sokol/sapp/enums.v b/vlib/sokol/sapp/enums.c.v similarity index 87% rename from vlib/sokol/sapp/enums.v rename to vlib/sokol/sapp/enums.c.v index b3e538076..863543731 100644 --- a/vlib/sokol/sapp/enums.v +++ b/vlib/sokol/sapp/enums.c.v @@ -36,33 +36,17 @@ pub enum MouseButton { } pub enum MouseCursor { - default = 0 - arrow = 1 - ibeam = 2 - crosshair = 3 - pointing_hand = 4 - resize_ew = 5 - resize_ns = 6 - resize_nwse = 7 - resize_nesw = 8 - resize_all = 9 - not_allowed = 10 - custom_0 = 11 - custom_1 = 12 - custom_2 = 13 - custom_3 = 14 - custom_4 = 15 - custom_5 = 16 - custom_6 = 17 - custom_7 = 18 - custom_8 = 19 - custom_9 = 20 - custom_10 = 21 - custom_11 = 22 - custom_12 = 23 - custom_13 = 24 - custom_14 = 25 - custom_15 = 26 + 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 { diff --git a/vlib/sokol/sapp/sapp.v b/vlib/sokol/sapp/sapp.c.v similarity index 60% rename from vlib/sokol/sapp/sapp.v rename to vlib/sokol/sapp/sapp.c.v index 9e2b0b3fa..da70105b3 100644 --- a/vlib/sokol/sapp/sapp.v +++ b/vlib/sokol/sapp/sapp.c.v @@ -5,9 +5,8 @@ import sokol.gfx import sokol.memory // Android needs a global reference to `g_desc` -__global g_desc Desc +__global g_desc C.sapp_desc -// create_desc creates a default `gfx.Desc` configured for use with `sapp`. pub fn create_desc() gfx.Desc { return gfx.Desc{ environment: glue_environment() @@ -23,46 +22,28 @@ pub fn create_default_pass(action gfx.PassAction) gfx.Pass { } } -// sapp_to_gfx_pixel_format translates sapp_pixel_format to gfx.PixelFormat. -// sokol_app.h uses a compact pixel format enum (sapp_pixel_format) that does NOT -// match the sg_pixel_format numbering used by sokol_gfx.h. -fn sapp_to_gfx_pixel_format(sapp_fmt int) gfx.PixelFormat { - return match sapp_fmt { - 0 { gfx.PixelFormat._default } // _SAPP_PIXELFORMAT_DEFAULT - 1 { gfx.PixelFormat.none } // SAPP_PIXELFORMAT_NONE - 2 { gfx.PixelFormat.rgba8 } // SAPP_PIXELFORMAT_RGBA8 - 3 { gfx.PixelFormat.srgb8a8 } // SAPP_PIXELFORMAT_SRGB8A8 - 4 { gfx.PixelFormat.bgra8 } // SAPP_PIXELFORMAT_BGRA8 - 5 { gfx.PixelFormat.bgra8 } // SAPP_PIXELFORMAT_SBGRA8 (no exact sg match, use bgra8) - 6 { gfx.PixelFormat.depth } // SAPP_PIXELFORMAT_DEPTH - 7 { gfx.PixelFormat.depth_stencil } // SAPP_PIXELFORMAT_DEPTH_STENCIL - else { gfx.PixelFormat.none } - } -} - // glue_environment returns a `gfx.Environment` compatible for use with `sapp` specific `gfx.Pass`es. -// The returned `gfx.Environment` can be used when rendering via `sapp`. +// 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_pixel_format(sapp_env.defaults.color_format) - env.defaults.depth_format = sapp_to_gfx_pixel_format(sapp_env.defaults.depth_format) + env.defaults.color_format = gfx.PixelFormat.from(sapp_env.defaults.color_format) or { + gfx.PixelFormat.none + } + env.defaults.depth_format = gfx.PixelFormat.from(sapp_env.defaults.depth_format) or { + gfx.PixelFormat.none + } env.defaults.sample_count = sapp_env.defaults.sample_count $if macos && !darwin_sokol_glcore33 ? { env.metal.device = sapp_env.metal.device } - // if windows and dx3d11 - // env.d3d11.device = sapp_env.d3d11.device - // env.d3d11.device_context = sapp_env.d3d11.device_context - // if webgpu - // env.wgpu.device = sapp_env.wgpu.device return env } // glue_swapchain returns a `gfx.Swapchain` compatible for use with `sapp` specific display/rendering `gfx.Pass`es. -// The returned `gfx.Swapchain` can be used when rendering via `sapp`. +// 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() @@ -71,22 +52,13 @@ pub fn glue_swapchain() gfx.Swapchain { swapchain.width = sapp_sc.width swapchain.height = sapp_sc.height swapchain.sample_count = sapp_sc.sample_count - swapchain.color_format = sapp_to_gfx_pixel_format(sapp_sc.color_format) - swapchain.depth_format = sapp_to_gfx_pixel_format(sapp_sc.depth_format) + swapchain.color_format = gfx.PixelFormat.from(sapp_sc.color_format) or { gfx.PixelFormat.none } + swapchain.depth_format = gfx.PixelFormat.from(sapp_sc.depth_format) or { gfx.PixelFormat.none } $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 - } - // if windows and dx3d11 - // swapchain.d3d11.render_view = sapp_sc.d3d11.render_view - // swapchain.d3d11.resolve_view = sapp_sc.d3d11.resolve_view - // swapchain.d3d11.depth_stencil_view = sapp_sc.d3d11.depth_stencil_view - // if webgpu - // swapchain.wgpu.render_view = sapp_sc.wgpu.render_view - // swapchain.wgpu.resolve_view = sapp_sc.wgpu.resolve_view - // swapchain.wgpu.depth_stencil_view = sapp_sc.wgpu.depth_stencil_view - $else { + } $else { swapchain.gl.framebuffer = sapp_sc.gl.framebuffer } return swapchain @@ -164,37 +136,17 @@ pub fn set_mouse_cursor(cursor MouseCursor) { C.sapp_set_mouse_cursor(cursor) } -// get current mouse cursor type -@[inline] -pub fn get_mouse_cursor() MouseCursor { - return C.sapp_get_mouse_cursor() -} - -// bind a custom mouse cursor image to a cursor type -@[inline] -pub fn bind_mouse_cursor_image(cursor MouseCursor, desc &ImageDesc) MouseCursor { - return C.sapp_bind_mouse_cursor_image(cursor, desc) -} - -// unbind a custom mouse cursor image -@[inline] -pub fn unbind_mouse_cursor_image(cursor MouseCursor) { - C.sapp_unbind_mouse_cursor_image(cursor) -} - // show or hide the mouse cursor @[inline] pub fn mouse_shown() bool { return C.sapp_mouse_shown() } -// lock_mouse locks or unlocks the mouse cursor, confining it to the window. @[inline] pub fn lock_mouse(locked bool) { C.sapp_lock_mouse(locked) } -// mouse_locked returns true if the mouse is currently locked to the window. @[inline] pub fn mouse_locked() bool { return C.sapp_mouse_locked() @@ -260,12 +212,6 @@ pub fn get_clipboard_string() &char { return &char(C.sapp_get_clipboard_string()) } -// set the window icon (only on Windows and Linux) -@[inline] -pub fn set_icon(icon_desc &IconDesc) { - C.sapp_set_icon(icon_desc) -} - // 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 } { @@ -284,42 +230,12 @@ pub fn run(desc &Desc) { C.sapp_run(desc) } -// get runtime environment information -@[inline] -pub fn get_environment() Environment { - return C.sapp_get_environment() -} - -// get current frame's swapchain information (call once per frame!) -@[inline] -pub fn get_swapchain() Swapchain { - return C.sapp_get_swapchain() -} - // 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) } -// HTML5: get byte size of a dropped file -@[inline] -pub fn html5_get_dropped_file_size(index int) u32 { - return C.sapp_html5_get_dropped_file_size(index) -} - -// EGL: get EGLDisplay object -@[inline] -pub fn egl_get_display() voidptr { - return C.sapp_egl_get_display() -} - -// EGL: get EGLContext object -@[inline] -pub fn egl_get_context() voidptr { - return C.sapp_egl_get_context() -} - // macOS: get ARC-bridged pointer to macOS NSWindow @[inline] pub fn macos_get_window() voidptr { @@ -332,52 +248,22 @@ pub fn ios_get_window() voidptr { return voidptr(C.sapp_ios_get_window()) } -// D3D11: get pointer to IDXGISwapChain object -@[inline] -pub fn d3d11_get_swap_chain() voidptr { - return voidptr(C.sapp_d3d11_get_swap_chain()) -} - // Win32: get the HWND window handle @[inline] pub fn win32_get_hwnd() voidptr { return voidptr(C.sapp_win32_get_hwnd()) } -// GL: get major version -@[inline] -pub fn gl_get_major_version() int { - return C.sapp_gl_get_major_version() -} - -// GL: get minor version -@[inline] -pub fn gl_get_minor_version() int { - return C.sapp_gl_get_minor_version() -} - -// GL: return true if the context is GLES -@[inline] -pub fn gl_is_gles() bool { - return C.sapp_gl_is_gles() -} - // GL: get framebuffer object @[inline] pub fn gl_get_framebuffer() u32 { return C.sapp_gl_get_framebuffer() } -// X11: get Window -@[inline] -pub fn x11_get_window() voidptr { - return voidptr(C.sapp_x11_get_window()) -} - -// X11: get Display +// Android: get native activity handle @[inline] -pub fn x11_get_display() voidptr { - return voidptr(C.sapp_x11_get_display()) +pub fn android_get_native_activity() voidptr { + return voidptr(C.sapp_android_get_native_activity()) } // Toggle full screen @@ -392,22 +278,14 @@ pub fn is_fullscreen() bool { return C.sapp_is_fullscreen() } -// get_num_dropped_files returns the number of files dropped onto the window. @[inline] pub fn get_num_dropped_files() int { return C.sapp_get_num_dropped_files() } -// get_dropped_file_path returns the path of a dropped file by index. @[inline] pub fn get_dropped_file_path(index int) string { unsafe { return cstring_to_vstring(C.sapp_get_dropped_file_path(index)) } } - -// Android: get native activity handle -@[inline] -pub fn android_get_native_activity() voidptr { - return voidptr(C.sapp_android_get_native_activity()) -} diff --git a/vlib/sokol/sapp/sapp_allocator_and_logger.c.v b/vlib/sokol/sapp/sapp_allocator_and_logger.c.v new file mode 100644 index 000000000..be73bba46 --- /dev/null +++ b/vlib/sokol/sapp/sapp_allocator_and_logger.c.v @@ -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 +} diff --git a/vlib/sokol/sapp/sapp_v.v b/vlib/sokol/sapp/sapp_v.c.v similarity index 88% rename from vlib/sokol/sapp/sapp_v.v rename to vlib/sokol/sapp/sapp_v.c.v index 9989e3dcb..c477d509b 100644 --- a/vlib/sokol/sapp/sapp_v.v +++ b/vlib/sokol/sapp/sapp_v.c.v @@ -3,6 +3,11 @@ 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`. @@ -42,7 +47,6 @@ pub fn screenshot_png(path string) ! { } // write_rgba_to_ppm writes `pixels` data in RGBA format to PPM3 format. -@[direct_array_access] fn write_rgba_to_ppm(path string, w int, h int, components int, pixels &u8) ! { mut f_out := os.create(path)! defer { diff --git a/vlib/sokol/sapp/screenshot.v b/vlib/sokol/sapp/screenshot.c.v similarity index 92% rename from vlib/sokol/sapp/screenshot.v rename to vlib/sokol/sapp/screenshot.c.v index 87d505a89..1934c9a60 100644 --- a/vlib/sokol/sapp/screenshot.v +++ b/vlib/sokol/sapp/screenshot.c.v @@ -9,7 +9,6 @@ mut: pixels &u8 = unsafe { nil } } -// screenshot_window captures a screenshot of the current window. @[manualfree] pub fn screenshot_window() &Screenshot { img_width := width() diff --git a/vlib/sokol/sfons/sfons.c.v b/vlib/sokol/sfons/sfons.c.v new file mode 100644 index 000000000..5008846f9 --- /dev/null +++ b/vlib/sokol/sfons/sfons.c.v @@ -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] +} diff --git a/vlib/sokol/sfons/sfons.v b/vlib/sokol/sfons/sfons.v deleted file mode 100644 index d0b0ddd72..000000000 --- a/vlib/sokol/sfons/sfons.v +++ /dev/null @@ -1,388 +0,0 @@ -module sfons - -import fontstash -import sokol.gfx -import sokol.sgl -import sokol.memory - -// Fontstash-specific fragment shaders. -// These differ from sgl's shaders: they read the .r channel for alpha, -// producing: frag_color = vec4(1.0, 1.0, 1.0, texture(tex_smp, uv).r) * color -// The vertex shader is identical to sgl's. - -const fs_source_glsl410 = '#version 410 - -uniform sampler2D tex_smp; -in vec2 uv; -in vec4 color; -layout(location = 0) out vec4 frag_color; - -void main() { - frag_color = vec4(1.0, 1.0, 1.0, texture(tex_smp, uv).r) * color; -} -' - -const fs_source_glsl300es = '#version 300 es -precision mediump float; -precision highp int; - -uniform highp sampler2D tex_smp; -in highp vec2 uv; -in highp vec4 color; -layout(location = 0) out highp vec4 frag_color; - -void main() { - frag_color = vec4(1.0, 1.0, 1.0, texture(tex_smp, uv).r) * color; -} -' - -// The vertex shader is the same as sgl's -const vs_source_glsl410 = '#version 410 - -uniform vec4 vs_params[8]; -layout(location = 0) in vec4 position; -layout(location = 1) in vec2 texcoord0; -layout(location = 2) in vec4 color0; -layout(location = 3) in float psize; -out vec2 uv; -out vec4 color; - -void main() { - gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position; - gl_PointSize = psize; - uv = (mat4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]) * vec4(texcoord0, 0.0, 1.0)).xy; - color = color0; -} -' - -const vs_source_glsl300es = '#version 300 es - -uniform vec4 vs_params[8]; -layout(location = 0) in vec4 position; -layout(location = 1) in vec2 texcoord0; -layout(location = 2) in vec4 color0; -layout(location = 3) in float psize; -out vec2 uv; -out vec4 color; - -void main() { - gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position; - gl_PointSize = psize; - uv = (mat4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]) * vec4(texcoord0, 0.0, 1.0)).xy; - color = color0; -} -' - -// Metal vertex shader source. -const vs_source_metal = '#include -using namespace metal; - -struct VSIn { - float4 position [[attribute(0)]]; - float2 texcoord0 [[attribute(1)]]; - float4 color0 [[attribute(2)]]; - float psize [[attribute(3)]]; -}; - -struct VSOut { - float4 position [[position]]; - float2 uv; - float4 color; - float psize [[point_size]]; -}; - -vertex VSOut main0(VSIn in [[stage_in]], constant float4* vs_params [[buffer(0)]]) { - VSOut out; - float4x4 mvp = float4x4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]); - float4x4 tm = float4x4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]); - out.position = mvp * in.position; - out.psize = in.psize; - out.uv = (tm * float4(in.texcoord0, 0.0, 1.0)).xy; - out.color = in.color0; - return out; -} -' - -// Metal fragment shader source. -const fs_source_metal = '#include -using namespace metal; - -struct FSIn { - float2 uv; - float4 color; - float psize [[point_size]]; -}; - -fragment float4 main0(FSIn in [[stage_in]], texture2d tex_smp [[texture(0)]], - sampler smp [[sampler(0)]]) { - return float4(1.0, 1.0, 1.0, tex_smp.sample(smp, in.uv).r) * in.color; -} -' - -// Internal state for sokol-fontstash -struct SFons { -mut: - shd gfx.Shader - pip sgl.Pipeline - img gfx.Image - smp gfx.Sampler - cur_width int - cur_height int - img_dirty bool - alloc_fn memory.FnAllocatorAlloc = unsafe { nil } - free_fn memory.FnAllocatorFree = unsafe { nil } - user_data voidptr -} - -fn make_shader_desc() gfx.ShaderDesc { - mut desc := gfx.ShaderDesc{} - desc.attrs[0].name = c'position' - desc.attrs[1].name = c'texcoord0' - desc.attrs[2].name = c'color0' - desc.attrs[3].name = c'psize' - desc.attrs[0].sem_name = c'TEXCOORD' - desc.attrs[0].sem_index = 0 - desc.attrs[1].sem_name = c'TEXCOORD' - desc.attrs[1].sem_index = 1 - desc.attrs[2].sem_name = c'TEXCOORD' - desc.attrs[2].sem_index = 2 - desc.attrs[3].sem_name = c'TEXCOORD' - desc.attrs[3].sem_index = 3 - desc.vs.uniform_blocks[0].size = 128 // 2 mat4 = 8 vec4 = 128 bytes - desc.vs.uniform_blocks[0].uniforms[0].name = c'vs_params' - desc.vs.uniform_blocks[0].uniforms[0].@type = .float4 - desc.vs.uniform_blocks[0].uniforms[0].array_count = 8 - desc.fs.images[0].used = true - desc.fs.images[0].image_type = ._2d - desc.fs.images[0].sample_type = .float - desc.fs.samplers[0].used = true - desc.fs.samplers[0].sampler_type = .filtering - desc.fs.image_sampler_pairs[0].used = true - desc.fs.image_sampler_pairs[0].image_slot = 0 - desc.fs.image_sampler_pairs[0].sampler_slot = 0 - desc.fs.image_sampler_pairs[0].glsl_name = c'tex_smp' - desc.label = c'sfons-shader' - - backend := gfx.query_backend() - match backend { - .glcore33 { - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .gles3 { - desc.vs.source = &char(vs_source_glsl300es.str) - desc.fs.source = &char(fs_source_glsl300es.str) - } - .metal_macos, .metal_ios, .metal_simulator { - desc.vs.entry = c'main0' - desc.fs.entry = c'main0' - desc.vs.source = &char(vs_source_metal.str) - desc.fs.source = &char(fs_source_metal.str) - } - .d3d11 { - // TODO: embed HLSL shader bytecode - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .wgpu { - // TODO: embed WGSL shader source - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .dummy { - desc.vs.source = c'' - desc.fs.source = c'' - } - } - return desc -} - -// Rendering callbacks for fontstash - -fn sfons_render_create(user_ptr voidptr, width int, height int) int { - assert user_ptr != unsafe { nil } - assert width > 8 - assert height > 8 - mut sf := unsafe { &SFons(user_ptr) } - - // Create shader if not yet created - if sf.shd.id == 0 { - shd_desc := make_shader_desc() - sf.shd = gfx.make_shader(&shd_desc) - $if trace_sfons ? { - eprintln('[sfons] shader created: id=${sf.shd.id}') - } - } - - // Create sgl pipeline if not yet created - if sf.pip.id == 0 { - mut pip_desc := gfx.PipelineDesc{} - pip_desc.shader = sf.shd - pip_desc.colors[0].blend.enabled = true - pip_desc.colors[0].blend.src_factor_rgb = .src_alpha - pip_desc.colors[0].blend.dst_factor_rgb = .one_minus_src_alpha - sf.pip = sgl.make_pipeline(&pip_desc) - $if trace_sfons ? { - eprintln('[sfons] pipeline created: id=${sf.pip.id}') - } - } - - // Create sampler if not yet created - if sf.smp.id == 0 { - smp_desc := gfx.SamplerDesc{ - min_filter: .linear - mag_filter: .linear - mipmap_filter: .none - } - sf.smp = gfx.make_sampler(&smp_desc) - } - - // Destroy and recreate font atlas texture - if sf.img.id != 0 { - gfx.destroy_image(sf.img) - sf.img = gfx.Image{} - } - sf.cur_width = width - sf.cur_height = height - - img_desc := gfx.ImageDesc{ - width: sf.cur_width - height: sf.cur_height - usage: .dynamic - pixel_format: .r8 - } - sf.img = gfx.make_image(&img_desc) - $if trace_sfons ? { - eprintln('[sfons] render_create: ${width}x${height} img.id=${sf.img.id} smp.id=${sf.smp.id} pip.id=${sf.pip.id} shd.id=${sf.shd.id}') - } - return 1 -} - -fn sfons_render_resize(user_ptr voidptr, width int, height int) int { - return sfons_render_create(user_ptr, width, height) -} - -fn sfons_render_update(user_ptr voidptr, _rect &int, _data &u8) { - assert user_ptr != unsafe { nil } - mut sf := unsafe { &SFons(user_ptr) } - sf.img_dirty = true -} - -fn sfons_render_draw(user_ptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) { - assert user_ptr != unsafe { nil } - assert nverts > 0 - sf := unsafe { &SFons(user_ptr) } - $if trace_sfons ? { - eprintln('[sfons] render_draw: nverts=${nverts} img.id=${sf.img.id} smp.id=${sf.smp.id} pip.id=${sf.pip.id}') - if nverts > 0 { - unsafe { - eprintln('[sfons] vert[0]: pos=(${verts[0]}, ${verts[1]}) uv=(${tcoords[0]}, ${tcoords[1]}) col=0x${colors[0]:08x}') - } - } - } - sgl.enable_texture() - sgl.texture(sf.img, sf.smp) - sgl.push_pipeline() - sgl.load_pipeline(sf.pip) - sgl.begin_triangles() - for i in 0 .. nverts { - unsafe { - sgl.v2f_t2f_c1i(verts[2 * i], verts[2 * i + 1], tcoords[2 * i], tcoords[2 * i + 1], - colors[i]) - } - } - sgl.end() - sgl.pop_pipeline() - sgl.disable_texture() -} - -fn sfons_render_delete(user_ptr voidptr) { - assert user_ptr != unsafe { nil } - mut sf := unsafe { &SFons(user_ptr) } - if sf.img.id != 0 { - gfx.destroy_image(sf.img) - sf.img = gfx.Image{} - } - if sf.smp.id != 0 { - gfx.destroy_sampler(sf.smp) - sf.smp = gfx.Sampler{} - } - if sf.pip.id != 0 { - sgl.destroy_pipeline(sf.pip) - sf.pip = sgl.Pipeline{} - } - if sf.shd.id != 0 { - gfx.destroy_shader(sf.shd) - sf.shd = gfx.Shader{} - } -} - -// Public API - -// create a new Context/font atlas, for rendering glyphs, given its dimensions `width` and `height` -pub fn create(width int, height int, flags int) &fontstash.Context { - assert is_power_of_two(width) - assert is_power_of_two(height) - - w := if width == 0 { 512 } else { width } - h := if height == 0 { 512 } else { height } - - // Allocate the internal state - sf := unsafe { &SFons(C.calloc(1, sizeof(SFons))) } - - params := C.FONSparams{ - width: w - height: h - flags: char(flags) - userPtr: voidptr(sf) - renderCreate: sfons_render_create - renderResize: sfons_render_resize - renderUpdate: sfons_render_update - renderDraw: sfons_render_draw - renderDelete: sfons_render_delete - } - return fontstash.create_internal(¶ms) -} - -// destroy frees the font stash context and associated resources. -pub fn destroy(ctx &fontstash.Context) { - // Get the SFons pointer from the context's params before destroying - sfons_ptr := unsafe { (&C.FONScontext(ctx)).params.userPtr } - fontstash.delete_internal(ctx) - unsafe { C.free(sfons_ptr) } -} - -// rgba packs RGBA color components into a single u32 value. -pub fn rgba(r u8, g u8, b u8, a u8) u32 { - return u32(r) | (u32(g) << 8) | (u32(b) << 16) | (u32(a) << 24) -} - -// flush uploads the font texture to the GPU and renders any pending text. -pub fn flush(ctx &fontstash.Context) { - fctx := unsafe { &C.FONScontext(ctx) } - sf := unsafe { &SFons(fctx.params.userPtr) } - if sf.img_dirty { - unsafe { - mut s := &SFons(fctx.params.userPtr) - s.img_dirty = false - } - mut img_data := gfx.ImageData{} - img_data.subimage[0][0] = gfx.Range{ - ptr: unsafe { fctx.texData } - size: usize(sf.cur_width * sf.cur_height) - } - $if trace_sfons ? { - eprintln('[sfons] flush: uploading texture ${sf.cur_width}x${sf.cur_height} to img.id=${sf.img.id} texData=${voidptr(fctx.texData)}') - } - gfx.update_image(sf.img, &img_data) - } - $if trace_sfons ? { - if !sf.img_dirty { - eprintln('[sfons] flush: not dirty') - } - } -} - -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] -} diff --git a/vlib/sokol/sfons/sfons_funcs.c.v b/vlib/sokol/sfons/sfons_funcs.c.v new file mode 100644 index 000000000..18059764e --- /dev/null +++ b/vlib/sokol/sfons/sfons_funcs.c.v @@ -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(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 diff --git a/vlib/sokol/sgl/enums.c.v b/vlib/sokol/sgl/enums.c.v new file mode 100644 index 000000000..77b745944 --- /dev/null +++ b/vlib/sokol/sgl/enums.c.v @@ -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 +} diff --git a/vlib/sokol/sgl/enums.v b/vlib/sokol/sgl/enums.v deleted file mode 100644 index 2d73c0a3a..000000000 --- a/vlib/sokol/sgl/enums.v +++ /dev/null @@ -1,36 +0,0 @@ -module sgl - -pub enum SglError { - no_error - vertices_full - uniforms_full - commands_full - stack_overflow - stack_underflow - no_context -} - -enum PrimitiveType { - points - lines - line_strip - triangles - triangle_strip - quads -} - -const num_primitive_types = 6 - -enum CommandType { - draw - viewport - scissor_rect -} - -enum MatrixMode { - modelview - projection - texture -} - -const num_matrixmodes = 3 diff --git a/vlib/sokol/sgl/matrix.v b/vlib/sokol/sgl/matrix.v deleted file mode 100644 index 971223473..000000000 --- a/vlib/sokol/sgl/matrix.v +++ /dev/null @@ -1,242 +0,0 @@ -module sgl - -import math - -@[direct_array_access] -fn mat4_identity(mut m Matrix) { - for c in 0 .. 4 { - for r in 0 .. 4 { - m.v[c][r] = if r == c { f32(1.0) } else { f32(0.0) } - } - } -} - -@[direct_array_access] -fn mat4_transpose(mut dst Matrix, m &Matrix) { - for c in 0 .. 4 { - for r in 0 .. 4 { - dst.v[r][c] = m.v[c][r] - } - } -} - -// mat4_mul multiplies two 4x4 matrices: p = a * b -@[direct_array_access] -fn mat4_mul(mut p Matrix, a &Matrix, b &Matrix) { - for r in 0 .. 4 { - ai0 := a.v[0][r] - ai1 := a.v[1][r] - ai2 := a.v[2][r] - ai3 := a.v[3][r] - p.v[0][r] = ai0 * b.v[0][0] + ai1 * b.v[0][1] + ai2 * b.v[0][2] + ai3 * b.v[0][3] - p.v[1][r] = ai0 * b.v[1][0] + ai1 * b.v[1][1] + ai2 * b.v[1][2] + ai3 * b.v[1][3] - p.v[2][r] = ai0 * b.v[2][0] + ai1 * b.v[2][1] + ai2 * b.v[2][2] + ai3 * b.v[2][3] - p.v[3][r] = ai0 * b.v[3][0] + ai1 * b.v[3][1] + ai2 * b.v[3][2] + ai3 * b.v[3][3] - } -} - -// mat4_mul_inplace multiplies dst by m in place: dst = dst * m -fn mat4_mul_inplace(mut dst Matrix, m &Matrix) { - mut tmp := Matrix{} - mat4_mul(mut tmp, dst, m) - unsafe { - *dst = tmp - } -} - -@[direct_array_access] -fn mat4_rotate(mut dst Matrix, a f32, x_ f32, y_ f32, z_ f32) { - mut x := x_ - mut y := y_ - mut z := z_ - s := math.sinf(a) - c := math.cosf(a) - - mag := math.sqrtf(x * x + y * y + z * z) - if mag < 1.0e-4 { - return - } - x /= mag - y /= mag - z /= mag - xx := x * x - yy := y * y - zz := z * z - xy := x * y - yz := y * z - zx := z * x - xs := x * s - ys := y * s - zs := z * s - one_c := f32(1.0) - c - - mut m := Matrix{} - m.v[0][0] = (one_c * xx) + c - m.v[1][0] = (one_c * xy) - zs - m.v[2][0] = (one_c * zx) + ys - m.v[3][0] = 0.0 - m.v[0][1] = (one_c * xy) + zs - m.v[1][1] = (one_c * yy) + c - m.v[2][1] = (one_c * yz) - xs - m.v[3][1] = 0.0 - m.v[0][2] = (one_c * zx) - ys - m.v[1][2] = (one_c * yz) + xs - m.v[2][2] = (one_c * zz) + c - m.v[3][2] = 0.0 - m.v[0][3] = 0.0 - m.v[1][3] = 0.0 - m.v[2][3] = 0.0 - m.v[3][3] = 1.0 - mat4_mul_inplace(mut dst, &m) -} - -@[direct_array_access] -fn mat4_scale(mut dst Matrix, x f32, y f32, z f32) { - for r in 0 .. 4 { - dst.v[0][r] *= x - dst.v[1][r] *= y - dst.v[2][r] *= z - } -} - -@[direct_array_access] -fn mat4_translate(mut dst Matrix, x f32, y f32, z f32) { - for r in 0 .. 4 { - dst.v[3][r] = dst.v[0][r] * x + dst.v[1][r] * y + dst.v[2][r] * z + dst.v[3][r] - } -} - -@[direct_array_access] -fn mat4_frustum(mut dst Matrix, left f32, right f32, bottom f32, top f32, znear f32, zfar f32) { - x := (2.0 * znear) / (right - left) - y := (2.0 * znear) / (top - bottom) - a := (right + left) / (right - left) - b := (top + bottom) / (top - bottom) - c := -(zfar + znear) / (zfar - znear) - d := -(2.0 * zfar * znear) / (zfar - znear) - mut m := Matrix{} - m.v[0][0] = x - m.v[0][1] = 0.0 - m.v[0][2] = 0.0 - m.v[0][3] = 0.0 - m.v[1][0] = 0.0 - m.v[1][1] = y - m.v[1][2] = 0.0 - m.v[1][3] = 0.0 - m.v[2][0] = a - m.v[2][1] = b - m.v[2][2] = c - m.v[2][3] = -1.0 - m.v[3][0] = 0.0 - m.v[3][1] = 0.0 - m.v[3][2] = d - m.v[3][3] = 0.0 - mat4_mul_inplace(mut dst, &m) -} - -@[direct_array_access] -fn mat4_ortho(mut dst Matrix, left f32, right f32, bottom f32, top f32, znear f32, zfar f32) { - mut m := Matrix{} - m.v[0][0] = 2.0 / (right - left) - m.v[1][0] = 0.0 - m.v[2][0] = 0.0 - m.v[3][0] = -(right + left) / (right - left) - m.v[0][1] = 0.0 - m.v[1][1] = 2.0 / (top - bottom) - m.v[2][1] = 0.0 - m.v[3][1] = -(top + bottom) / (top - bottom) - m.v[0][2] = 0.0 - m.v[1][2] = 0.0 - m.v[2][2] = -2.0 / (zfar - znear) - m.v[3][2] = -(zfar + znear) / (zfar - znear) - m.v[0][3] = 0.0 - m.v[1][3] = 0.0 - m.v[2][3] = 0.0 - m.v[3][3] = 1.0 - mat4_mul_inplace(mut dst, &m) -} - -@[direct_array_access] -fn mat4_perspective(mut dst Matrix, fovy f32, aspect f32, znear f32, zfar f32) { - sine := math.sinf(fovy / 2.0) - delta_z := zfar - znear - if delta_z == 0.0 || sine == 0.0 || aspect == 0.0 { - return - } - cotan := math.cosf(fovy / 2.0) / sine - mut m := Matrix{} - mat4_identity(mut m) - m.v[0][0] = cotan / aspect - m.v[1][1] = cotan - m.v[2][2] = -(zfar + znear) / delta_z - m.v[2][3] = -1.0 - m.v[3][2] = -2.0 * znear * zfar / delta_z - m.v[3][3] = 0.0 - mat4_mul_inplace(mut dst, &m) -} - -@[direct_array_access] -fn vec3_normalize(mut v [3]f32) { - r := math.sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) - if r == 0.0 { - return - } - v[0] /= r - v[1] /= r - v[2] /= r -} - -@[direct_array_access] -fn vec3_cross(v1 [3]f32, v2 [3]f32) [3]f32 { - return [ - v1[1] * v2[2] - v1[2] * v2[1], - v1[2] * v2[0] - v1[0] * v2[2], - v1[0] * v2[1] - v1[1] * v2[0], - ]! -} - -@[direct_array_access] -fn mat4_lookat(mut dst Matrix, 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) { - mut fwd := [center_x - eye_x, center_y - eye_y, center_z - eye_z]! - mut up := [up_x, up_y, up_z]! - vec3_normalize(mut fwd) - mut side := vec3_cross(fwd, up) - vec3_normalize(mut side) - up = vec3_cross(side, fwd) - - mut m := Matrix{} - mat4_identity(mut m) - m.v[0][0] = side[0] - m.v[1][0] = side[1] - m.v[2][0] = side[2] - m.v[0][1] = up[0] - m.v[1][1] = up[1] - m.v[2][1] = up[2] - m.v[0][2] = -fwd[0] - m.v[1][2] = -fwd[1] - m.v[2][2] = -fwd[2] - mat4_mul_inplace(mut dst, &m) - mat4_translate(mut dst, -eye_x, -eye_y, -eye_z) -} - -// Matrix stack access helpers for ContextInternal - -fn (ctx &ContextInternal) matrix_projection() &Matrix { - return &ctx.matrix_stack[int(MatrixMode.projection)][ctx.matrix_tos[int(MatrixMode.projection)]] -} - -fn (ctx &ContextInternal) matrix_modelview() &Matrix { - return &ctx.matrix_stack[int(MatrixMode.modelview)][ctx.matrix_tos[int(MatrixMode.modelview)]] -} - -fn (ctx &ContextInternal) matrix_texture() &Matrix { - return &ctx.matrix_stack[int(MatrixMode.texture)][ctx.matrix_tos[int(MatrixMode.texture)]] -} - -fn (ctx &ContextInternal) current_matrix() &Matrix { - return &ctx.matrix_stack[int(ctx.cur_matrix_mode)][ctx.matrix_tos[int(ctx.cur_matrix_mode)]] -} - -fn (mut ctx ContextInternal) current_matrix_mut() &Matrix { - return &ctx.matrix_stack[int(ctx.cur_matrix_mode)][ctx.matrix_tos[int(ctx.cur_matrix_mode)]] -} diff --git a/vlib/sokol/sgl/sgl.c.v b/vlib/sokol/sgl/sgl.c.v new file mode 100644 index 000000000..5d413e2bb --- /dev/null +++ b/vlib/sokol/sgl/sgl.c.v @@ -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) +} diff --git a/vlib/sokol/sgl/sgl.v b/vlib/sokol/sgl/sgl.v deleted file mode 100644 index 4e95a7bb9..000000000 --- a/vlib/sokol/sgl/sgl.v +++ /dev/null @@ -1,1676 +0,0 @@ -@[has_globals] -module sgl - -import math -import sokol.gfx -import sokol.memory - -pub const version = gfx.version + 1 - -pub const default_context = Context{0x00010001} - -__global sgl_state = SglState{} - -// ======================== -// Pool Management -// ======================== - -fn init_pool(mut pool Pool, num int) { - pool.size = num + 1 - pool.queue_top = 0 - pool.gen_ctrs = unsafe { &u32(C.calloc(usize(pool.size), sizeof(u32))) } - pool.free_queue = unsafe { &int(C.calloc(usize(num), sizeof(int))) } - // fill free queue in reverse order - for i := pool.size - 1; i >= 1; i-- { - unsafe { - pool.free_queue[pool.queue_top] = i - } - pool.queue_top++ - } -} - -fn discard_pool(mut pool Pool) { - unsafe { - C.free(pool.free_queue) - pool.free_queue = nil - C.free(pool.gen_ctrs) - pool.gen_ctrs = nil - } - pool.size = 0 - pool.queue_top = 0 -} - -fn pool_alloc_index(mut pool Pool) int { - if pool.queue_top > 0 { - pool.queue_top-- - return unsafe { pool.free_queue[pool.queue_top] } - } - return invalid_slot_index -} - -fn pool_free_index(mut pool Pool, slot_index int) { - unsafe { - pool.free_queue[pool.queue_top] = slot_index - } - pool.queue_top++ -} - -fn slot_alloc(mut pool Pool, mut s Slot, slot_index int) u32 { - unsafe { - pool.gen_ctrs[slot_index]++ - ctr := pool.gen_ctrs[slot_index] - s.id = (ctr << slot_shift) | u32(slot_index & slot_mask) - s.state = .alloc - return s.id - } -} - -fn slot_index(id u32) int { - return int(id & slot_mask) -} - -// ======================== -// Pipeline Management -// ======================== - -fn setup_pipeline_pool(pool_size int) { - init_pool(mut sgl_state.pip_pool.pool, pool_size) - pool_byte_size := usize(sgl_state.pip_pool.pool.size) * sizeof(PipelineInternal) - sgl_state.pip_pool.pips = unsafe { &PipelineInternal(C.calloc(1, pool_byte_size)) } -} - -fn discard_pipeline_pool() { - unsafe { C.free(sgl_state.pip_pool.pips) } - sgl_state.pip_pool.pips = unsafe { nil } - discard_pool(mut sgl_state.pip_pool.pool) -} - -fn pipeline_at(pip_id u32) &PipelineInternal { - idx := slot_index(pip_id) - return unsafe { &sgl_state.pip_pool.pips[idx] } -} - -fn lookup_pipeline(pip_id u32) &PipelineInternal { - if pip_id != 0 { - pip := pipeline_at(pip_id) - if pip.slot.id == pip_id { - return pip - } - } - return unsafe { nil } -} - -fn alloc_pipeline() Pipeline { - idx := pool_alloc_index(mut sgl_state.pip_pool.pool) - if idx != invalid_slot_index { - mut s := unsafe { &sgl_state.pip_pool.pips[idx].slot } - id := slot_alloc(mut sgl_state.pip_pool.pool, mut s, idx) - return Pipeline{id} - } - return Pipeline{0} -} - -@[direct_array_access] -fn init_pipeline(pip_id Pipeline, in_desc &gfx.PipelineDesc, ctx_desc &ContextDesc) { - assert pip_id.id != 0 - - mut desc := unsafe { *in_desc } - desc.layout.buffers[0].stride = int(sizeof(Vertex)) - - desc.layout.attrs[0].offset = 0 // pos: offset 0 - desc.layout.attrs[0].format = .float3 - desc.layout.attrs[1].offset = int(sizeof([3]f32)) // uv: after pos (3 floats = 12 bytes) - desc.layout.attrs[1].format = .float2 - desc.layout.attrs[2].offset = int(sizeof([3]f32) + sizeof([2]f32)) // rgba: after uv (5 floats = 20 bytes) - desc.layout.attrs[2].format = .ubyte4n - desc.layout.attrs[3].offset = int(sizeof([3]f32) + sizeof([2]f32) + sizeof(u32)) // psize: after rgba (24 bytes) - desc.layout.attrs[3].format = .float - - if in_desc.shader.id == 0 { - desc.shader = sgl_state.shd - } - desc.index_type = .none - desc.sample_count = ctx_desc.sample_count - if int(desc.face_winding) == 0 { - desc.face_winding = sgl_state.desc.face_winding - } - desc.depth.pixel_format = ctx_desc.depth_format - if ctx_desc.depth_format == .none { - desc.depth.write_enabled = false - } - desc.colors[0].pixel_format = ctx_desc.color_format - if int(desc.colors[0].write_mask) == 0 { - desc.colors[0].write_mask = .rgb - } - - pip := lookup_pipeline(pip_id.id) - assert pip != unsafe { nil } - assert pip.slot.state == .alloc - unsafe { - mut p := pip - p.slot.state = .valid - for i in 0 .. num_primitive_types { - prim := PrimitiveType(i) - match prim { - .points { desc.primitive_type = .points } - .lines { desc.primitive_type = .lines } - .line_strip { desc.primitive_type = .line_strip } - .triangles { desc.primitive_type = .triangles } - .triangle_strip { desc.primitive_type = .triangle_strip } - .quads { desc.primitive_type = .triangles } - } - if prim == .quads { - // quads emulated as triangles, reuse same pipeline - p.pip[i] = p.pip[int(PrimitiveType.triangles)] - } else { - p.pip[i] = gfx.make_pipeline(&desc) - } - } - } -} - -fn internal_make_pipeline(desc &gfx.PipelineDesc, ctx_desc &ContextDesc) Pipeline { - pip_id := alloc_pipeline() - if pip_id.id != 0 { - init_pipeline(pip_id, desc, ctx_desc) - } - return pip_id -} - -@[direct_array_access] -fn internal_destroy_pipeline(pip_id Pipeline) { - pip := lookup_pipeline(pip_id.id) - if pip != unsafe { nil } { - C.sg_push_debug_group(c'sokol-gl') - unsafe { - mut p := pip - for i in 0 .. num_primitive_types { - if i != int(PrimitiveType.quads) { - gfx.destroy_pipeline(p.pip[i]) - } - } - p.slot = Slot{} - } - C.sg_pop_debug_group() - pool_free_index(mut sgl_state.pip_pool.pool, slot_index(pip_id.id)) - } -} - -fn get_pipeline(pip Pipeline, prim_type PrimitiveType) gfx.Pipeline { - p := lookup_pipeline(pip.id) - if p != unsafe { nil } { - return p.pip[int(prim_type)] - } - return gfx.Pipeline{} -} - -// ======================== -// Context Management -// ======================== - -fn setup_context_pool(pool_size int) { - init_pool(mut sgl_state.context_pool.pool, pool_size) - pool_byte_size := usize(sgl_state.context_pool.pool.size) * sizeof(ContextInternal) - sgl_state.context_pool.contexts = unsafe { &ContextInternal(C.calloc(1, pool_byte_size)) } -} - -fn discard_context_pool() { - unsafe { C.free(sgl_state.context_pool.contexts) } - sgl_state.context_pool.contexts = unsafe { nil } - discard_pool(mut sgl_state.context_pool.pool) -} - -fn context_at(ctx_id u32) &ContextInternal { - idx := slot_index(ctx_id) - return unsafe { &sgl_state.context_pool.contexts[idx] } -} - -fn lookup_context(ctx_id u32) &ContextInternal { - if ctx_id != 0 { - ctx := context_at(ctx_id) - if ctx.slot.id == ctx_id { - return ctx - } - } - return unsafe { nil } -} - -fn alloc_context() Context { - idx := pool_alloc_index(mut sgl_state.context_pool.pool) - if idx != invalid_slot_index { - mut s := unsafe { &sgl_state.context_pool.contexts[idx].slot } - id := slot_alloc(mut sgl_state.context_pool.pool, mut s, idx) - return Context{id} - } - return Context{0} -} - -fn context_desc_defaults(desc &ContextDesc) ContextDesc { - mut res := unsafe { *desc } - if res.max_vertices == 0 { - res.max_vertices = default_max_vertices - } - if res.max_commands == 0 { - res.max_commands = default_max_commands - } - return res -} - -fn as_context_desc(desc &Desc) ContextDesc { - return ContextDesc{ - max_vertices: desc.max_vertices - max_commands: desc.max_commands - color_format: desc.color_format - depth_format: desc.depth_format - sample_count: desc.sample_count - } -} - -fn commit_listener_cb(userdata voidptr) { - ctx_id := u32(usize(userdata)) - ctx := lookup_context(ctx_id) - if ctx != unsafe { nil } { - rewind_context(ctx) - } -} - -fn make_commit_listener(ctx &ContextInternal) gfx.CommitListener { - return gfx.CommitListener{ - func: commit_listener_cb - user_data: voidptr(usize(ctx.slot.id)) - } -} - -@[direct_array_access] -fn init_context(ctx_id Context, in_desc &ContextDesc) { - ctx := lookup_context(ctx_id.id) - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - c.desc = context_desc_defaults(in_desc) - c.frame_id = 1 - c.cur_img = sgl_state.def_img - c.cur_smp = sgl_state.def_smp - - // allocate buffers - c.vertices_cap = c.desc.max_vertices - c.uniforms_cap = c.desc.max_commands - c.commands_cap = c.desc.max_commands - c.vertices_ptr = &Vertex(C.calloc(usize(c.vertices_cap), sizeof(Vertex))) - c.uniforms_ptr = &Uniform(C.calloc(usize(c.uniforms_cap), sizeof(Uniform))) - c.commands_ptr = &Command(C.calloc(usize(c.commands_cap), sizeof(Command))) - - // create sokol-gfx resources - C.sg_push_debug_group(c'sokol-gl') - vbuf_desc := gfx.BufferDesc{ - @type: .vertexbuffer - usage: .stream - size: usize(c.vertices_cap) * sizeof(Vertex) - label: c'sgl-vertex-buffer' - } - c.vbuf = gfx.make_buffer(&vbuf_desc) - c.bind.vertex_buffers[0] = c.vbuf - - def_pip_desc := gfx.PipelineDesc{ - depth: gfx.DepthState{ - write_enabled: true - } - } - c.def_pip = internal_make_pipeline(&def_pip_desc, &c.desc) - C.sg_add_commit_listener(make_commit_listener(ctx)) - C.sg_pop_debug_group() - - // initialize state - c.rgba = 0xFFFFFFFF - c.point_size = 1.0 - for i in 0 .. num_matrixmodes { - mat4_identity(mut c.matrix_stack[i][0]) - } - c.pip_stack[0] = c.def_pip - c.matrix_dirty = true - } -} - -fn internal_make_context(desc &ContextDesc) Context { - ctx_id := alloc_context() - if ctx_id.id != 0 { - init_context(ctx_id, desc) - } - return ctx_id -} - -fn internal_destroy_context(ctx_id Context) { - ctx := lookup_context(ctx_id.id) - if ctx != unsafe { nil } { - unsafe { - C.free(ctx.vertices_ptr) - C.free(ctx.uniforms_ptr) - C.free(ctx.commands_ptr) - mut c := ctx - c.vertices_ptr = nil - c.uniforms_ptr = nil - c.commands_ptr = nil - } - C.sg_push_debug_group(c'sokol-gl') - gfx.destroy_buffer(ctx.vbuf) - internal_destroy_pipeline(ctx.def_pip) - C.sg_remove_commit_listener(make_commit_listener(ctx)) - C.sg_pop_debug_group() - - unsafe { - mut c := ctx - c.slot = Slot{} - } - pool_free_index(mut sgl_state.context_pool.pool, slot_index(ctx_id.id)) - } -} - -// ======================== -// Common Resources -// ======================== - -@[direct_array_access] -fn setup_common() { - // 8x8 white default texture - mut pixels := [64]u32{} - for i in 0 .. 64 { - pixels[i] = 0xFFFFFFFF - } - mut img_desc := gfx.ImageDesc{ - @type: ._2d - width: 8 - height: 8 - num_mipmaps: 1 - pixel_format: .rgba8 - label: c'sgl-default-texture' - } - img_desc.data.subimage[0][0] = gfx.Range{ - ptr: unsafe { &pixels[0] } - size: sizeof([64]u32) - } - sgl_state.def_img = gfx.make_image(&img_desc) - - // default sampler (nearest filtering) - smp_desc := gfx.SamplerDesc{ - min_filter: .nearest - mag_filter: .nearest - } - sgl_state.def_smp = gfx.make_sampler(&smp_desc) - - // create shader - shd_desc := make_shader_desc() - sgl_state.shd = gfx.make_shader(&shd_desc) -} - -fn discard_common() { - gfx.destroy_shader(sgl_state.shd) - gfx.destroy_sampler(sgl_state.def_smp) - gfx.destroy_image(sgl_state.def_img) -} - -// ======================== -// Vertex / Command Helpers -// ======================== - -fn next_vertex(ctx &ContextInternal) &Vertex { - unsafe { - mut c := ctx - if c.vertices_next < c.vertices_cap { - vtx := &c.vertices_ptr[c.vertices_next] - c.vertices_next++ - return vtx - } else { - c.error = .vertices_full - return nil - } - } -} - -fn next_uniform(ctx &ContextInternal) &Uniform { - unsafe { - mut c := ctx - if c.uniforms_next < c.uniforms_cap { - uni := &c.uniforms_ptr[c.uniforms_next] - c.uniforms_next++ - return uni - } else { - c.error = .uniforms_full - return nil - } - } -} - -fn next_command(ctx &ContextInternal) &Command { - unsafe { - mut c := ctx - if c.commands_next < c.commands_cap { - cmd := &c.commands_ptr[c.commands_next] - c.commands_next++ - return cmd - } else { - c.error = .commands_full - return nil - } - } -} - -fn cur_command(ctx &ContextInternal) &Command { - if ctx.commands_next > 0 { - return unsafe { &ctx.commands_ptr[ctx.commands_next - 1] } - } - return unsafe { nil } -} - -@[inline] -fn next_draw_chunk(base_vertex int, remaining_vertices int, max_vertices int) (int, int) { - chunk_vertices := if max_vertices > 0 && remaining_vertices > max_vertices { - max_vertices - } else { - remaining_vertices - } - return base_vertex, chunk_vertices -} - -@[direct_array_access] -fn vtx(ctx &ContextInternal, x f32, y f32, z f32, u_ f32, v_ f32, rgba_ u32) { - unsafe { - mut c := ctx - // quad emulation: before 4th vertex, duplicate 1st and 3rd to form second triangle - if c.cur_prim_type == .quads && (c.vtx_count & 3) == 3 { - // save vertex data before next_vertex increments vertices_next - v0 := c.vertices_ptr[c.vertices_next - 3] - v2 := c.vertices_ptr[c.vertices_next - 1] - vtx1 := next_vertex(ctx) - if vtx1 != nil { - *vtx1 = v0 - } - vtx2 := next_vertex(ctx) - if vtx2 != nil { - *vtx2 = v2 - } - } - v := next_vertex(ctx) - if v != nil { - v.pos[0] = x - v.pos[1] = y - v.pos[2] = z - v.uv[0] = u_ - v.uv[1] = v_ - v.rgba = rgba_ - v.psize = c.point_size - } - c.vtx_count++ - } -} - -fn rewind_context(ctx &ContextInternal) { - unsafe { - mut c := ctx - c.frame_id++ - c.vertices_next = 0 - c.uniforms_next = 0 - c.commands_next = 0 - c.base_vertex = 0 - c.error = .no_error - c.layer_id = 0 - c.matrix_dirty = true - } -} - -fn begin_(ctx &ContextInternal, mode PrimitiveType) { - unsafe { - mut c := ctx - c.in_begin = true - c.base_vertex = c.vertices_next - c.vtx_count = 0 - c.cur_prim_type = mode - } -} - -fn desc_defaults(desc &Desc) Desc { - mut res := unsafe { *desc } - if res.max_vertices == 0 { - res.max_vertices = default_max_vertices - } - if res.max_commands == 0 { - res.max_commands = default_max_commands - } - if res.context_pool_size == 0 { - res.context_pool_size = default_context_pool_size - } - if res.pipeline_pool_size == 0 { - res.pipeline_pool_size = default_pipeline_pool_size - } - if int(res.face_winding) == 0 { - res.face_winding = .ccw - } - return res -} - -// ======================== -// Draw (command playback) -// ======================== - -@[direct_array_access] -fn internal_draw(ctx &ContextInternal, layer_id int) { - if ctx.error != .no_error || ctx.vertices_next == 0 || ctx.commands_next == 0 { - return - } - C.sg_push_debug_group(c'sokol-gl') - - mut cur_pip_id := u32(0) - mut cur_img_id := u32(0) - mut cur_smp_id := u32(0) - mut cur_uniform_index := -1 - - unsafe { - mut c := ctx - if c.update_frame_id != c.frame_id { - c.update_frame_id = c.frame_id - range := gfx.Range{ - ptr: c.vertices_ptr - size: usize(c.vertices_next) * sizeof(Vertex) - } - gfx.update_buffer(c.vbuf, &range) - } - } - for i in 0 .. ctx.commands_next { - cmd := unsafe { &ctx.commands_ptr[i] } - if cmd.layer_id != layer_id { - continue - } - match cmd.cmd { - .viewport { - args := unsafe { &cmd.args.viewport } - gfx.apply_viewport(args.x, args.y, args.w, args.h, args.origin_top_left) - } - .scissor_rect { - args := unsafe { &cmd.args.scissor_rect } - gfx.apply_scissor_rect(args.x, args.y, args.w, args.h, args.origin_top_left) - } - .draw { - args := unsafe { &cmd.args.draw } - if args.pip.id != cur_pip_id { - gfx.apply_pipeline(args.pip) - cur_pip_id = args.pip.id - // force rebind after pipeline change - cur_img_id = 0 - cur_smp_id = 0 - cur_uniform_index = -1 - } - if args.img.id != cur_img_id || args.smp.id != cur_smp_id { - unsafe { - mut c := ctx - c.bind.fs.images[0] = args.img - c.bind.fs.samplers[0] = args.smp - } - gfx.apply_bindings(&ctx.bind) - cur_img_id = args.img.id - cur_smp_id = args.smp.id - } - if cur_uniform_index != args.uniform_index { - ub_range := gfx.Range{ - ptr: unsafe { &ctx.uniforms_ptr[args.uniform_index] } - size: sizeof(Uniform) - } - gfx.apply_uniforms(.vs, 0, &ub_range) - cur_uniform_index = args.uniform_index - } - if args.num_vertices > 0 { - if args.max_vertices > 0 && args.num_vertices > args.max_vertices { - mut base_vertex := args.base_vertex - mut remaining_vertices := args.num_vertices - for remaining_vertices > 0 { - chunk_base_vertex, chunk_vertices := next_draw_chunk(base_vertex, - remaining_vertices, args.max_vertices) - gfx.draw(chunk_base_vertex, chunk_vertices, 1) - base_vertex += chunk_vertices - remaining_vertices -= chunk_vertices - } - } else { - gfx.draw(args.base_vertex, args.num_vertices, 1) - } - } - } - } - } - C.sg_pop_debug_group() -} - -// ======================== -// PUBLIC API -// ======================== - -// setup/shutdown - -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 - } - } - unsafe { C.memset(&sgl_state, 0, sizeof(SglState)) } - sgl_state.init_cookie = init_cookie - sgl_state.desc = desc_defaults(desc) - setup_pipeline_pool(sgl_state.desc.pipeline_pool_size) - setup_context_pool(sgl_state.desc.context_pool_size) - setup_common() - ctx_desc := as_context_desc(&sgl_state.desc) - sgl_state.def_ctx_id = internal_make_context(&ctx_desc) - set_context(sgl_state.def_ctx_id) -} - -pub fn shutdown() { - // destroy contexts first (they own pipelines) - for i in 0 .. sgl_state.context_pool.pool.size { - ctx := unsafe { &sgl_state.context_pool.contexts[i] } - internal_destroy_context(Context{ctx.slot.id}) - } - for i in 0 .. sgl_state.pip_pool.pool.size { - pip := unsafe { &sgl_state.pip_pool.pips[i] } - internal_destroy_pipeline(Pipeline{pip.slot.id}) - } - discard_context_pool() - discard_pipeline_pool() - discard_common() - sgl_state.init_cookie = 0 -} - -@[inline] -pub fn error() SglError { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - return ctx.error - } - return .no_context -} - -@[inline] -pub fn context_error(ctx_handle Context) SglError { - ctx := lookup_context(ctx_handle.id) - if ctx != unsafe { nil } { - return ctx.error - } - return .no_context -} - -@[inline] -pub fn rad(deg f32) f32 { - return deg * (math.pi / 180.0) -} - -@[inline] -pub fn deg(r f32) f32 { - return r * (180.0 / math.pi) -} - -// context functions -@[inline] -pub fn make_context(desc &ContextDesc) Context { - return internal_make_context(desc) -} - -@[inline] -pub fn destroy_context(ctx Context) { - internal_destroy_context(ctx) -} - -@[inline] -pub fn set_context(ctx Context) { - sgl_state.cur_ctx_id = ctx - sgl_state.cur_ctx = lookup_context(ctx.id) -} - -@[inline] -pub fn get_context() Context { - return sgl_state.cur_ctx_id -} - -@[inline] -pub fn default_context() Context { - return sgl_state.def_ctx_id -} - -// pipeline functions -@[inline] -pub fn make_pipeline(desc &gfx.PipelineDesc) Pipeline { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - return internal_make_pipeline(desc, &ctx.desc) - } - return Pipeline{0} -} - -@[inline] -pub fn context_make_pipeline(ctx_handle Context, desc &gfx.PipelineDesc) Pipeline { - ctx := lookup_context(ctx_handle.id) - if ctx != unsafe { nil } { - return internal_make_pipeline(desc, &ctx.desc) - } - return Pipeline{0} -} - -@[inline] -pub fn destroy_pipeline(pip Pipeline) { - internal_destroy_pipeline(pip) -} - -// render state -pub fn defaults() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - c.u = 0.0 - c.v = 0.0 - c.rgba = 0xFFFFFFFF - c.point_size = 1.0 - c.texturing_enabled = false - c.cur_img = sgl_state.def_img - c.cur_smp = sgl_state.def_smp - } - load_default_pipeline() - unsafe { - mut c := ctx - mat4_identity(mut c.matrix_stack[int(MatrixMode.texture)][c.matrix_tos[int(MatrixMode.texture)]]) - mat4_identity(mut c.matrix_stack[int(MatrixMode.modelview)][c.matrix_tos[int(MatrixMode.modelview)]]) - mat4_identity(mut c.matrix_stack[int(MatrixMode.projection)][c.matrix_tos[int(MatrixMode.projection)]]) - c.cur_matrix_mode = .modelview - c.matrix_dirty = true - } -} - -@[inline] -pub fn viewport(x int, y int, w int, h int, origin_top_left bool) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - cmd := next_command(ctx) - if cmd != unsafe { nil } { - unsafe { - mut c := cmd - c.cmd = .viewport - c.layer_id = ctx.layer_id - mut a := &ViewportArgs(&c.args) - a.x = x - a.y = y - a.w = w - a.h = h - a.origin_top_left = origin_top_left - } - } -} - -@[inline] -pub fn viewportf(x f32, y f32, w f32, h f32, origin_top_left bool) { - viewport(int(x), int(y), int(w), int(h), origin_top_left) -} - -@[inline] -pub fn scissor_rect(x int, y int, w int, h int, origin_top_left bool) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - cmd := next_command(ctx) - if cmd != unsafe { nil } { - unsafe { - mut c := cmd - c.cmd = .scissor_rect - c.layer_id = ctx.layer_id - mut a := &ScissorRectArgs(&c.args) - a.x = x - a.y = y - a.w = w - a.h = h - a.origin_top_left = origin_top_left - } - } -} - -@[inline] -pub fn scissor_rectf(x f32, y f32, w f32, h f32, origin_top_left bool) { - scissor_rect(int(x), int(y), int(w), int(h), origin_top_left) -} - -@[inline] -pub fn enable_texture() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.texturing_enabled = true - } - } -} - -@[inline] -pub fn disable_texture() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.texturing_enabled = false - } - } -} - -@[inline] -pub fn texture(img gfx.Image, smp gfx.Sampler) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.cur_img = img - c.cur_smp = smp - } - } -} - -@[inline] -pub fn layer(layer_id int) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.layer_id = layer_id - } - } -} - -// pipeline stack - -@[inline] -pub fn load_default_pipeline() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.pip_stack[c.pip_tos] = c.def_pip - c.matrix_dirty = true - } - } -} - -@[inline] -pub fn default_pipeline() { - load_default_pipeline() -} - -@[inline] -pub fn load_pipeline(pip Pipeline) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.pip_stack[c.pip_tos] = pip - c.matrix_dirty = true - } - } -} - -@[inline] -pub fn push_pipeline() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - if c.pip_tos < max_stack_depth - 1 { - c.pip_tos++ - c.pip_stack[c.pip_tos] = c.pip_stack[c.pip_tos - 1] - } else { - c.error = .stack_overflow - } - } -} - -@[inline] -pub fn pop_pipeline() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - if c.pip_tos > 0 { - c.pip_tos-- - } else { - c.error = .stack_underflow - } - } -} - -// matrix functions - -@[inline] -pub fn matrix_mode_modelview() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.cur_matrix_mode = .modelview - } - } -} - -@[inline] -pub fn matrix_mode_projection() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.cur_matrix_mode = .projection - } - } -} - -@[inline] -pub fn matrix_mode_texture() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.cur_matrix_mode = .texture - } - } -} - -@[inline] -pub fn load_identity() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_identity(mut m) - } - } -} - -@[direct_array_access; inline] -pub fn load_matrix(m []f32) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } || m.len < 16 { - return - } - unsafe { - mut c := ctx - c.matrix_dirty = true - mut dst := c.current_matrix_mut() - for col in 0 .. 4 { - for row in 0 .. 4 { - dst.v[col][row] = m[col * 4 + row] - } - } - } -} - -@[direct_array_access; inline] -pub fn load_transpose_matrix(m []f32) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } || m.len < 16 { - return - } - unsafe { - mut c := ctx - c.matrix_dirty = true - mut dst := c.current_matrix_mut() - for col in 0 .. 4 { - for row in 0 .. 4 { - dst.v[col][row] = m[row * 4 + col] - } - } - } -} - -@[direct_array_access; inline] -pub fn mult_matrix(m []f32) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } || m.len < 16 { - return - } - unsafe { - mut c := ctx - c.matrix_dirty = true - mut src := Matrix{} - for col in 0 .. 4 { - for row in 0 .. 4 { - src.v[col][row] = m[col * 4 + row] - } - } - mut dst := c.current_matrix_mut() - mat4_mul_inplace(mut dst, &src) - } -} - -@[direct_array_access; inline] -pub fn mult_transpose_matrix(m []f32) { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } || m.len < 16 { - return - } - unsafe { - mut c := ctx - c.matrix_dirty = true - mut src := Matrix{} - for col in 0 .. 4 { - for row in 0 .. 4 { - src.v[col][row] = m[row * 4 + col] - } - } - mut dst := c.current_matrix_mut() - mat4_mul_inplace(mut dst, &src) - } -} - -@[inline] -pub fn rotate(angle_rad f32, x f32, y f32, z f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_rotate(mut m, angle_rad, x, y, z) - } - } -} - -@[inline] -pub fn scale(x f32, y f32, z f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_scale(mut m, x, y, z) - } - } -} - -@[inline] -pub fn translate(x f32, y f32, z f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_translate(mut m, x, y, z) - } - } -} - -@[inline] -pub fn frustum(l f32, r f32, b f32, t f32, n f32, f f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_frustum(mut m, l, r, b, t, n, f) - } - } -} - -@[inline] -pub fn ortho(l f32, r f32, b f32, t f32, n f32, f f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_ortho(mut m, l, r, b, t, n, f) - } - } -} - -@[inline] -pub fn perspective(fov_y f32, aspect f32, z_near f32, z_far f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_perspective(mut m, 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) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.matrix_dirty = true - mut m := c.current_matrix_mut() - mat4_lookat(mut m, eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, - up_y, up_z) - } - } -} - -@[inline] -pub fn push_matrix() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - mode := int(c.cur_matrix_mode) - if c.matrix_tos[mode] < max_stack_depth - 1 { - c.matrix_tos[mode]++ - c.matrix_stack[mode][c.matrix_tos[mode]] = c.matrix_stack[mode][c.matrix_tos[mode] - 1] - } else { - c.error = .stack_overflow - } - } -} - -@[inline] -pub fn pop_matrix() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - unsafe { - mut c := ctx - mode := int(c.cur_matrix_mode) - if c.matrix_tos[mode] > 0 { - c.matrix_tos[mode]-- - c.matrix_dirty = true - } else { - c.error = .stack_underflow - } - } -} - -// texcoord / color / point size - -@[inline] -pub fn t2f(u f32, v f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.u = u - c.v = v - } - } -} - -// c3f sets the current color using RGB float values (0.0-1.0). -@[inline] -pub fn c3f(r f32, g f32, b f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.rgba = pack_rgbaf(r, g, b, 1.0) - } - } -} - -// c4f sets the current color using RGBA float values (0.0-1.0). -@[inline] -pub fn c4f(r f32, g f32, b f32, a f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.rgba = pack_rgbaf(r, g, b, a) - } - } -} - -// c3b sets the current color using RGB byte values (0-255). -@[inline] -pub fn c3b(r u8, g u8, b u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.rgba = pack_rgba(r, g, b, 255) - } - } -} - -// c4b sets the current color using RGBA byte values (0-255). -@[inline] -pub fn c4b(r u8, g u8, b u8, a u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.rgba = pack_rgba(r, g, b, a) - } - } -} - -// c1i sets the current color using a packed RGBA u32 value. -@[inline] -pub fn c1i(rgba u32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.rgba = rgba - } - } -} - -// point_size sets the size of points when drawing point primitives. -@[inline] -pub fn point_size(s f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - unsafe { - mut c := ctx - c.point_size = s - } - } -} - -// color packing helpers - -@[inline] -fn pack_rgba(r u8, g u8, b u8, a u8) u32 { - return u32(r) | (u32(g) << 8) | (u32(b) << 16) | (u32(a) << 24) -} - -@[inline] -fn pack_rgbaf(r f32, g f32, b f32, a f32) u32 { - r_ := u8(r * 255.0) - g_ := u8(g * 255.0) - b_ := u8(b * 255.0) - a_ := u8(a * 255.0) - return pack_rgba(r_, g_, b_, a_) -} - -// primitives - -// begin_points begins drawing points. -@[inline] -pub fn begin_points() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .points) - } -} - -// begin_lines begins drawing lines. -@[inline] -pub fn begin_lines() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .lines) - } -} - -// begin_line_strip begins drawing a line strip (connected lines). -@[inline] -pub fn begin_line_strip() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .line_strip) - } -} - -// begin_triangles begins drawing triangles. -@[inline] -pub fn begin_triangles() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .triangles) - } -} - -// begin_triangle_strip begins drawing a triangle strip. -@[inline] -pub fn begin_triangle_strip() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .triangle_strip) - } -} - -// begin_quads begins drawing quads. -@[inline] -pub fn begin_quads() { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - begin_(ctx, .quads) - } -} - -// vertex submission - -// v2f submits a 2D vertex position. -@[inline] -pub fn v2f(x f32, y f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, ctx.rgba) - } -} - -// v3f submits a 3D vertex position. -@[inline] -pub fn v3f(x f32, y f32, z f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, ctx.rgba) - } -} - -// v2f_t2f submits a 2D vertex with texture coordinates. -@[inline] -pub fn v2f_t2f(x f32, y f32, u f32, v f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, u, v, ctx.rgba) - } -} - -// v3f_t2f submits a 3D vertex with texture coordinates. -@[inline] -pub fn v3f_t2f(x f32, y f32, z f32, u f32, v f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, ctx.rgba) - } -} - -// v2f_c3f submits a 2D vertex with RGB color (float). -@[inline] -pub fn v2f_c3f(x f32, y f32, r f32, g f32, b f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, pack_rgbaf(r, g, b, 1.0)) - } -} - -// v2f_c3b submits a 2D vertex with RGB color (bytes). -@[inline] -pub fn v2f_c3b(x f32, y f32, r u8, g u8, b u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, pack_rgba(r, g, b, 255)) - } -} - -// v2f_c4f submits a 2D vertex with RGBA color (float). -@[inline] -pub fn v2f_c4f(x f32, y f32, r f32, g f32, b f32, a f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, pack_rgbaf(r, g, b, a)) - } -} - -// v2f_c4b submits a 2D vertex with RGBA color (bytes). -@[inline] -pub fn v2f_c4b(x f32, y f32, r u8, g u8, b u8, a u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, pack_rgba(r, g, b, a)) - } -} - -// v2f_c1i submits a 2D vertex with packed RGBA color. -@[inline] -pub fn v2f_c1i(x f32, y f32, rgba u32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, ctx.u, ctx.v, rgba) - } -} - -// v3f_c3f submits a 3D vertex with RGB color (float). -@[inline] -pub fn v3f_c3f(x f32, y f32, z f32, r f32, g f32, b f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, pack_rgbaf(r, g, b, 1.0)) - } -} - -// v3f_c3b submits a 3D vertex with RGB color (bytes). -@[inline] -pub fn v3f_c3b(x f32, y f32, z f32, r u8, g u8, b u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, pack_rgba(r, g, b, 255)) - } -} - -@[inline] -pub fn v3f_c4f(x f32, y f32, z f32, r f32, g f32, b f32, a f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, pack_rgbaf(r, g, b, a)) - } -} - -@[inline] -pub fn v3f_c4b(x f32, y f32, z f32, r u8, g u8, b u8, a u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, pack_rgba(r, g, b, a)) - } -} - -@[inline] -pub fn v3f_c1i(x f32, y f32, z f32, rgba u32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, ctx.u, ctx.v, rgba) - } -} - -@[inline] -pub fn v2f_t2f_c3f(x f32, y f32, u f32, v f32, r f32, g f32, b f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, u, v, pack_rgbaf(r, g, b, 1.0)) - } -} - -@[inline] -pub fn v2f_t2f_c3b(x f32, y f32, u f32, v f32, r u8, g u8, b u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, u, v, pack_rgba(r, g, b, 255)) - } -} - -@[inline] -pub fn v2f_t2f_c4f(x f32, y f32, u f32, v f32, r f32, g f32, b f32, a f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, u, v, pack_rgbaf(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) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, u, v, pack_rgba(r, g, b, a)) - } -} - -@[inline] -pub fn v2f_t2f_c1i(x f32, y f32, u f32, v f32, rgba u32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, 0.0, 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) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, pack_rgbaf(r, g, b, 1.0)) - } -} - -@[inline] -pub fn v3f_t2f_c3b(x f32, y f32, z f32, u f32, v f32, r u8, g u8, b u8) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, pack_rgba(r, g, b, 255)) - } -} - -@[inline] -pub fn v3f_t2f_c4f(x f32, y f32, z f32, u f32, v f32, r f32, g f32, b f32, a f32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, pack_rgbaf(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) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, pack_rgba(r, g, b, a)) - } -} - -@[inline] -pub fn v3f_t2f_c1i(x f32, y f32, z f32, u f32, v f32, rgba u32) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - vtx(ctx, x, y, z, u, v, rgba) - } -} - -// end primitive and record draw command - -pub fn end() { - ctx := sgl_state.cur_ctx - if ctx == unsafe { nil } { - return - } - assert ctx.in_begin - - unsafe { - mut c := ctx - c.in_begin = false - } - matrix_dirty := ctx.matrix_dirty - if matrix_dirty { - unsafe { - mut c := ctx - c.matrix_dirty = false - } - uni := next_uniform(ctx) - if uni != unsafe { nil } { - unsafe { - mut u := uni - mat4_mul(mut u.mvp, ctx.matrix_projection(), ctx.matrix_modelview()) - u.tm = *ctx.matrix_texture() - } - } - } - - // check if command can be merged with current command - pip := get_pipeline(ctx.pip_stack[ctx.pip_tos], ctx.cur_prim_type) - img := if ctx.texturing_enabled { ctx.cur_img } else { sgl_state.def_img } - smp := if ctx.texturing_enabled { ctx.cur_smp } else { sgl_state.def_smp } - - prev_cmd := cur_command(ctx) - mut merge := false - if prev_cmd != unsafe { nil } { - prev_draw := unsafe { &prev_cmd.args.draw } - if prev_cmd.cmd == .draw && prev_cmd.layer_id == ctx.layer_id - && ctx.cur_prim_type != .line_strip && ctx.cur_prim_type != .triangle_strip - && !matrix_dirty && prev_draw.img.id == img.id && prev_draw.smp.id == smp.id - && prev_draw.pip.id == pip.id { - merge = true - } - } - - if merge { - // extend previous draw command - unsafe { - mut draw_args := &DrawArgs(&prev_cmd.args) - draw_args.num_vertices += ctx.vertices_next - ctx.base_vertex - } - } else { - // new draw command - cmd := next_command(ctx) - if cmd != unsafe { nil } { - assert ctx.uniforms_next > 0 - unsafe { - mut c := cmd - c.cmd = .draw - c.layer_id = ctx.layer_id - mut a := &DrawArgs(&c.args) - a.img = img - a.smp = smp - a.pip = pip - a.base_vertex = ctx.base_vertex - a.num_vertices = ctx.vertices_next - ctx.base_vertex - a.uniform_index = ctx.uniforms_next - 1 - a.max_vertices = if ctx.cur_prim_type == .points { - max_point_batch_vertices - } else { - 0 - } - } - } - } -} - -// render recorded commands - -@[inline] -pub fn draw() { - draw_layer(0) -} - -@[inline] -pub fn draw_layer(layer_id int) { - ctx := sgl_state.cur_ctx - if ctx != unsafe { nil } { - internal_draw(ctx, layer_id) - } -} - -@[inline] -pub fn context_draw(ctx_handle Context) { - context_draw_layer(ctx_handle, 0) -} - -@[inline] -pub fn context_draw_layer(ctx_handle Context, layer_id int) { - ctx := lookup_context(ctx_handle.id) - if ctx != unsafe { nil } { - internal_draw(ctx, layer_id) - } -} diff --git a/vlib/sokol/sgl/sgl_allocator_and_logger.c.v b/vlib/sokol/sgl/sgl_allocator_and_logger.c.v new file mode 100644 index 000000000..32f9d8c6d --- /dev/null +++ b/vlib/sokol/sgl/sgl_allocator_and_logger.c.v @@ -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 +} diff --git a/vlib/sokol/sgl/sgl_funcs.c.v b/vlib/sokol/sgl/sgl_funcs.c.v new file mode 100644 index 000000000..256d6ceca --- /dev/null +++ b/vlib/sokol/sgl/sgl_funcs.c.v @@ -0,0 +1,103 @@ +module sgl + +// setup/shutdown/misc +fn C.sgl_setup(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(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(desc &C.sg_pipeline_desc) C.sgl_pipeline +fn C.sgl_context_make_pipeline(ctx C.sgl_context, 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) diff --git a/vlib/sokol/sgl/sgl_structs.c.v b/vlib/sokol/sgl/sgl_structs.c.v new file mode 100644 index 000000000..5cd1db3c9 --- /dev/null +++ b/vlib/sokol/sgl/sgl_structs.c.v @@ -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)) +} diff --git a/vlib/sokol/sgl/sgl_structs.v b/vlib/sokol/sgl/sgl_structs.v deleted file mode 100644 index 6493ef0a8..000000000 --- a/vlib/sokol/sgl/sgl_structs.v +++ /dev/null @@ -1,222 +0,0 @@ -module sgl - -import sokol.gfx -import sokol.memory - -// Public types - -pub struct Pipeline { -pub: - id u32 -} - -pub struct Context { -pub: - id u32 -} - -pub struct ContextDesc { -pub mut: - max_vertices int - max_commands int - color_format gfx.PixelFormat - depth_format gfx.PixelFormat - sample_count int -} - -pub struct Allocator { -pub mut: - alloc_fn memory.FnAllocatorAlloc = unsafe { nil } - free_fn memory.FnAllocatorFree = unsafe { nil } - user_data voidptr -} - -pub struct Logger { -pub mut: - func memory.FnLogCb = unsafe { nil } - user_data voidptr -} - -pub struct Desc { -pub mut: - max_vertices int - max_commands int - context_pool_size int - pipeline_pool_size int - color_format gfx.PixelFormat - depth_format gfx.PixelFormat - sample_count int - face_winding gfx.FaceWinding - allocator Allocator - logger Logger -} - -// Internal structs used by the pure V implementation. - -struct Vertex { -mut: - pos [3]f32 - uv [2]f32 - rgba u32 - psize f32 -} - -struct Matrix { -mut: - v [4][4]f32 -} - -struct Uniform { -mut: - mvp Matrix - tm Matrix -} - -struct DrawArgs { -mut: - pip gfx.Pipeline - img gfx.Image - smp gfx.Sampler - base_vertex int - num_vertices int - uniform_index int - max_vertices int -} - -struct ViewportArgs { -mut: - x int - y int - w int - h int - origin_top_left bool -} - -struct ScissorRectArgs { -mut: - x int - y int - w int - h int - origin_top_left bool -} - -union CommandArgs { - draw DrawArgs - viewport ViewportArgs - scissor_rect ScissorRectArgs -} - -struct Command { -mut: - cmd CommandType - layer_id int - args CommandArgs -} - -struct Slot { -mut: - id u32 - state gfx.ResourceState -} - -struct Pool { -mut: - size int - queue_top int - gen_ctrs &u32 = unsafe { nil } - free_queue &int = unsafe { nil } -} - -struct PipelineInternal { -mut: - slot Slot - pip [num_primitive_types]gfx.Pipeline -} - -struct PipelinePool { -mut: - pool Pool - pips &PipelineInternal = unsafe { nil } -} - -const max_stack_depth = 64 - -struct ContextInternal { -mut: - slot Slot - desc ContextDesc - frame_id u32 - update_frame_id u32 - // vertex buffer - vertices_cap int - vertices_next int - vertices_ptr &Vertex = unsafe { nil } - // uniform buffer - uniforms_cap int - uniforms_next int - uniforms_ptr &Uniform = unsafe { nil } - // command buffer - commands_cap int - commands_next int - commands_ptr &Command = unsafe { nil } - // state tracking - base_vertex int - vtx_count int - error SglError - in_begin bool - layer_id int - u f32 - v f32 - rgba u32 - point_size f32 - cur_prim_type PrimitiveType - cur_img gfx.Image - cur_smp gfx.Sampler - texturing_enabled bool - matrix_dirty bool - // sokol-gfx resources - vbuf gfx.Buffer - def_pip Pipeline - bind gfx.Bindings - // pipeline stack - pip_tos int - pip_stack [max_stack_depth]Pipeline - // matrix stacks - cur_matrix_mode MatrixMode - matrix_tos [num_matrixmodes]int - matrix_stack [num_matrixmodes][max_stack_depth]Matrix -} - -struct ContextPool { -mut: - pool Pool - contexts &ContextInternal = unsafe { nil } -} - -// Global state -struct SglState { -mut: - init_cookie u32 - desc Desc - def_img gfx.Image - def_smp gfx.Sampler - shd gfx.Shader - def_ctx_id Context - cur_ctx_id Context - cur_ctx &ContextInternal = unsafe { nil } - pip_pool PipelinePool - context_pool ContextPool -} - -const invalid_slot_index = 0 -const default_context_pool_size = 4 -const default_pipeline_pool_size = 64 -const default_max_vertices = (1 << 17) -const default_max_commands = (1 << 15) -// Large point batches can disappear on some backends/drivers once they exceed 16-bit counts. -const max_point_batch_vertices = 0xFFFF -const slot_shift = 16 -const max_pool_size = (1 << slot_shift) -const slot_mask = (max_pool_size - 1) -const init_cookie = u32(0xABCDABCD) diff --git a/vlib/sokol/sgl/shaders.v b/vlib/sokol/sgl/shaders.v deleted file mode 100644 index af2be037f..000000000 --- a/vlib/sokol/sgl/shaders.v +++ /dev/null @@ -1,180 +0,0 @@ -module sgl - -import sokol.gfx - -// GLSL 410 vertex shader (for SOKOL_GLCORE - Linux/macOS/FreeBSD/OpenBSD/Windows) -const vs_source_glsl410 = '#version 410 - -uniform vec4 vs_params[8]; -layout(location = 0) in vec4 position; -layout(location = 1) in vec2 texcoord0; -layout(location = 2) in vec4 color0; -layout(location = 3) in float psize; -out vec2 uv; -out vec4 color; - -void main() { - gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position; - gl_PointSize = psize; - uv = (mat4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]) * vec4(texcoord0, 0.0, 1.0)).xy; - color = color0; -} -' - -// GLSL 410 fragment shader -const fs_source_glsl410 = '#version 410 - -uniform sampler2D tex_smp; -in vec2 uv; -in vec4 color; -layout(location = 0) out vec4 frag_color; - -void main() { - frag_color = texture(tex_smp, uv) * color; -} -' - -// GLES3 vertex shader (for SOKOL_GLES3 - Emscripten/mobile) -const vs_source_glsl300es = '#version 300 es - -uniform vec4 vs_params[8]; -layout(location = 0) in vec4 position; -layout(location = 1) in vec2 texcoord0; -layout(location = 2) in vec4 color0; -layout(location = 3) in float psize; -out vec2 uv; -out vec4 color; - -void main() { - gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position; - gl_PointSize = psize; - uv = (mat4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]) * vec4(texcoord0, 0.0, 1.0)).xy; - color = color0; -} -' - -// GLES3 fragment shader -const fs_source_glsl300es = '#version 300 es -precision mediump float; -precision highp int; - -uniform highp sampler2D tex_smp; -in highp vec2 uv; -in highp vec4 color; -layout(location = 0) out highp vec4 frag_color; - -void main() { - frag_color = texture(tex_smp, uv) * color; -} -' - -// Metal vertex shader source. -const vs_source_metal = '#include -using namespace metal; - -struct VSIn { - float4 position [[attribute(0)]]; - float2 texcoord0 [[attribute(1)]]; - float4 color0 [[attribute(2)]]; - float psize [[attribute(3)]]; -}; - -struct VSOut { - float4 position [[position]]; - float2 uv; - float4 color; - float psize [[point_size]]; -}; - -vertex VSOut main0(VSIn in [[stage_in]], constant float4* vs_params [[buffer(0)]]) { - VSOut out; - float4x4 mvp = float4x4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]); - float4x4 tm = float4x4(vs_params[4], vs_params[5], vs_params[6], vs_params[7]); - out.position = mvp * in.position; - out.psize = in.psize; - out.uv = (tm * float4(in.texcoord0, 0.0, 1.0)).xy; - out.color = in.color0; - return out; -} -' - -// Metal fragment shader source. -const fs_source_metal = '#include -using namespace metal; - -struct FSIn { - float2 uv; - float4 color; - float psize [[point_size]]; -}; - -fragment float4 main0(FSIn in [[stage_in]], texture2d tex_smp [[texture(0)]], - sampler smp [[sampler(0)]]) { - return tex_smp.sample(smp, in.uv) * in.color; -} -' - -// Builds and returns the shader descriptor for the sgl shader. -// Selects the correct shader source/bytecode based on the active graphics backend. -fn make_shader_desc() gfx.ShaderDesc { - mut desc := gfx.ShaderDesc{} - desc.attrs[0].name = c'position' - desc.attrs[1].name = c'texcoord0' - desc.attrs[2].name = c'color0' - desc.attrs[3].name = c'psize' - desc.attrs[0].sem_name = c'TEXCOORD' - desc.attrs[0].sem_index = 0 - desc.attrs[1].sem_name = c'TEXCOORD' - desc.attrs[1].sem_index = 1 - desc.attrs[2].sem_name = c'TEXCOORD' - desc.attrs[2].sem_index = 2 - desc.attrs[3].sem_name = c'TEXCOORD' - desc.attrs[3].sem_index = 3 - desc.vs.uniform_blocks[0].size = sizeof(Uniform) - desc.vs.uniform_blocks[0].uniforms[0].name = c'vs_params' - desc.vs.uniform_blocks[0].uniforms[0].@type = .float4 - desc.vs.uniform_blocks[0].uniforms[0].array_count = 8 - desc.fs.images[0].used = true - desc.fs.images[0].image_type = ._2d - desc.fs.images[0].sample_type = .float - desc.fs.samplers[0].used = true - desc.fs.samplers[0].sampler_type = .filtering - desc.fs.image_sampler_pairs[0].used = true - desc.fs.image_sampler_pairs[0].image_slot = 0 - desc.fs.image_sampler_pairs[0].sampler_slot = 0 - desc.fs.image_sampler_pairs[0].glsl_name = c'tex_smp' - desc.label = c'sgl-shader' - - backend := gfx.query_backend() - match backend { - .glcore33 { - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .gles3 { - desc.vs.source = &char(vs_source_glsl300es.str) - desc.fs.source = &char(fs_source_glsl300es.str) - } - .metal_macos, .metal_ios, .metal_simulator { - desc.vs.entry = c'main0' - desc.fs.entry = c'main0' - desc.vs.source = &char(vs_source_metal.str) - desc.fs.source = &char(fs_source_metal.str) - } - .d3d11 { - // D3D11 backend - TODO: embed HLSL shader bytecode - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .wgpu { - // WebGPU - TODO: embed WGSL shader source - desc.vs.source = &char(vs_source_glsl410.str) - desc.fs.source = &char(fs_source_glsl410.str) - } - .dummy { - desc.vs.source = c'' - desc.fs.source = c'' - } - } - return desc -} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 3cbbc942b..015781a01 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2076,7 +2076,7 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast. expr) c.cur_or_expr = last_cur_or_expr } - return ret_type.clear_flag(.result) + return ret_type.clear_option_and_result() } else if expr.left is ast.SelectorExpr && expr.left_type.has_option_or_result() { with_modifier_kind := if expr.left_type.has_flag(.option) { 'an Option' diff --git a/vlib/v/gen/c/autofree.v b/vlib/v/gen/c/autofree.v index 22cf7e76e..69e0a89e4 100644 --- a/vlib/v/gen/c/autofree.v +++ b/vlib/v/gen/c/autofree.v @@ -235,7 +235,7 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) { } mut af := strings.new_builder(128) if v.typ.is_ptr() && v.typ.idx() != ast.u8_type_idx { - if !v.is_auto_heap { + if !v.is_auto_heap && !g.table.sym(v.typ).has_method('free') { return } af.write_string('\t') diff --git a/vlib/v/gen/c/str_intp.v b/vlib/v/gen/c/str_intp.v index 2d99b79f5..d1a598d2f 100644 --- a/vlib/v/gen/c/str_intp.v +++ b/vlib/v/gen/c/str_intp.v @@ -414,7 +414,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) { g.expr(expr) g.write2('${dot}_object', ')') } else if fmt == `s` || typ.has_flag(.variadic) { - mut exp_typ := typ + mut exp_typ := orig_typ is_comptime_for_var := expr is ast.Ident && g.is_comptime_for_var(expr) if !is_comptime_for_var && expr is ast.Ident { if g.comptime.get_ct_type_var(expr) == .smartcast { diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index 498e03f08..b4c0677e8 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -1093,6 +1093,9 @@ fn (mut w Walker) fn_decl_with_fkey(mut node ast.FnDecl, walk_fkey string) { } pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) { + if node == unsafe { nil } { + return + } w.fn_decl_with_fkey(mut node, node.fkey()) } diff --git a/vlib/v/tests/generics/generics_map_with_reference_arg_test.v b/vlib/v/tests/generics/generics_map_with_reference_arg_test.v index f247d32c3..e49aa397d 100644 --- a/vlib/v/tests/generics/generics_map_with_reference_arg_test.v +++ b/vlib/v/tests/generics/generics_map_with_reference_arg_test.v @@ -47,7 +47,7 @@ pub fn (mut l Lru[T, V]) get(k T) ?V { l.list.delete(l.list.index(k) or { return none }) l.list.push_front(k) l.hits++ - return l.m[k].value + return (l.m[k] or { return none }).value } l.miss++ return none @@ -69,7 +69,7 @@ pub fn (mut l Lru[T, V]) remove_expired(cnt int) { pub fn (mut l Lru[T, V]) del(k T) { if k in l.m { - val := l.m[k].value + val := (l.m[k] or { return }).value l.m.delete(k) l.list.delete(l.list.index(k) or { -1 }) on_del := l.on_del or { return } -- 2.39.5