mirror of
https://github.com/Ed94/VEFontCache-Odin.git
synced 2025-08-06 23:12:43 -07:00
Compare commits
102 Commits
test_macos
...
dev
Author | SHA1 | Date | |
---|---|---|---|
7c3dbd8831 | |||
8ded4d55c9 | |||
be91e5e9d2 | |||
7e55703066 | |||
eaae5f32ca | |||
77f1466ae3 | |||
1bd2dc2333 | |||
de219704b8 | |||
6e0cb87338 | |||
17a061a790 | |||
0d0344e423 | |||
de8841a0cb | |||
14791e532e | |||
eec58a30e2 | |||
1ed9d48a71 | |||
d806fc6083 | |||
10080190c8 | |||
600bad337e | |||
d6da8ee84e | |||
f145281b6a | |||
4a355b7948 | |||
8aef144c6a | |||
d265e715fd | |||
d82245e031 | |||
a18e527367 | |||
25e7e874a9 | |||
a6a9f622f4 | |||
21cc8740ed | |||
cdbef8d656 | |||
3e861760db | |||
d7ae6d1d41 | |||
867cbee924 | |||
ca1cd05f2b | |||
14b9eda809 | |||
19fef22451 | |||
d4748ab306 | |||
19c3525096 | |||
6990c21377 | |||
4abb591e1c | |||
8f9cff4119 | |||
2a805d2de0 | |||
c8cd665d5f | |||
6bc7514ef0 | |||
7dd1bad72d | |||
d7560b4a89 | |||
33e0b227a0 | |||
4ff3edfed4 | |||
375825d34e | |||
3b2bf6e322 | |||
2e3b55b972 | |||
7bec503af7 | |||
cbbb48d631 | |||
8f491fd843 | |||
989be15390 | |||
207fa94803 | |||
470800af2a | |||
a47937f615 | |||
a4dafe01c8 | |||
e8218f3bf8 | |||
b220812950 | |||
046c69c477 | |||
f7e4278300 | |||
e8a7b21eba | |||
b78a544aa8 | |||
dbe97a7176 | |||
d56e1d608c | |||
a1b4bcf77f | |||
4f9de8f539 | |||
48927fd008 | |||
c64f8132dc | |||
87ab22c207 | |||
79498efbf3 | |||
a584497563 | |||
c995af36e7 | |||
3b59ac75bf | |||
7af3c49dfc | |||
4afa50f1df | |||
52584f888c | |||
91e8af8839 | |||
99a1f77699 | |||
a14e4faf29 | |||
572abf5d86 | |||
f6ea780747 | |||
2eb94e077f | |||
18decf3e46 | |||
ddfd529993 | |||
77cf07ce16 | |||
36cc557975 | |||
d329327555 | |||
c41e09f377 | |||
f1a47223ea | |||
e53abccc98 | |||
90ca01bdaa | |||
55a4c3dee6 | |||
137eea9da4 | |||
20e9a556ce | |||
cc411b0e1e | |||
f7071c2810 | |||
15192ff4b3 | |||
810d188b8f | |||
c2dbe91973 | |||
a8823c9776 |
77
.github/workflows/linux_build.yaml
vendored
Normal file
77
.github/workflows/linux_build.yaml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Linux Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
- '**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Odin
|
||||
uses: laytan/setup-odin@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up environment
|
||||
run: |
|
||||
if ! command -v git &> /dev/null; then
|
||||
echo "Git not found. Installing Git..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git
|
||||
else
|
||||
echo "Git is already installed."
|
||||
fi
|
||||
git --version
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential \
|
||||
bash \
|
||||
libfreetype6-dev \
|
||||
libharfbuzz-dev \
|
||||
libgl1-mesa-dev \
|
||||
libx11-dev \
|
||||
libxcursor-dev \
|
||||
libxrandr-dev \
|
||||
libxinerama-dev \
|
||||
libxi-dev \
|
||||
libglew-dev \
|
||||
libxtst-dev \
|
||||
libasound-dev
|
||||
|
||||
make -C "/home/runner/odin/vendor/stb/src"
|
||||
|
||||
- name: Run build script
|
||||
run: |
|
||||
echo "Setting execute permissions on specific .sh files"
|
||||
chmod +x ./scripts/build_sokol_demo.sh
|
||||
chmod +x ./scripts/build_sokol_library.sh
|
||||
chmod +x ./scripts/compile_sokol_shaders.sh
|
||||
chmod +x ./scripts/clean.sh
|
||||
chmod +x ./scripts/helpers/misc.sh
|
||||
chmod +x ./scripts/helpers/odin_compiler_defs.sh
|
||||
|
||||
echo "Running build_sokol_demo.sh"
|
||||
./scripts/build_sokol_demo.sh
|
||||
shell: bash
|
||||
|
||||
- name: List build artifacts
|
||||
run: ls -R ./build || echo "build directory not found"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-build
|
||||
path: ./build/
|
||||
if-no-files-found: warn
|
8
.github/workflows/macos_build.yaml
vendored
8
.github/workflows/macos_build.yaml
vendored
@@ -35,7 +35,11 @@ jobs:
|
||||
brew install harfbuzz
|
||||
brew install odin
|
||||
|
||||
make -C "/opt/homebrew/Cellar/odin/2024-10/libexec/vendor/stb/src"
|
||||
# Get the latest Odin directory dynamically
|
||||
ODIN_VER_DIR=$(ls /opt/homebrew/Cellar/odin/ | sort -r | head -n1)
|
||||
echo "ODIN_VER_DIR=$ODIN_VER_DIR" >> $GITHUB_ENV
|
||||
|
||||
make -C "/opt/homebrew/Cellar/odin/$ODIN_VER_DIR/libexec/vendor/stb/src"
|
||||
|
||||
- name: Run build script
|
||||
run: |
|
||||
@@ -55,7 +59,7 @@ jobs:
|
||||
run: ls -R ./build || echo "build directory not found"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-build
|
||||
path: ./build/
|
||||
|
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
build
|
||||
thirdparty
|
||||
.vscode
|
||||
backend/sokol/render_glyph.odin
|
||||
backend/sokol/blit_atlas.odin
|
||||
backend/sokol/draw_text.odin
|
||||
.vscode
|
||||
ols.json
|
||||
build
|
||||
# thirdparty/harfbuzz
|
||||
# thirdparty/sokol
|
||||
# thirdparty/sokol-tools
|
||||
|
@@ -1,4 +1,4 @@
|
||||
VEFontCache Odin Port
|
||||
VEFontCache Odin
|
||||
Copyright 2024 Edward R. Gonzalez
|
||||
|
||||
This project is based on Vertex Engine GPU Font Cache
|
||||
|
95
Readme.md
95
Readme.md
@@ -1,50 +1,75 @@
|
||||
# VE Font Cache : Odin Port
|
||||
# VE Font Cache
|
||||
|
||||
This is a port of the [VEFontCache](https://github.com/hypernewbie/VEFontCache) library.
|
||||
Vertex Engine GPU Font Cache: A text shaping & rendering library.
|
||||
|
||||
Its original purpose was for use in game engines, however its rendeirng quality and performance is more than adequate for many other applications.
|
||||
This project started as a port of the [VEFontCache](https://github.com/hypernewbie/VEFontCache) library to the Odin programming language.
|
||||
While originally intended for game engines, its rendering quality and performance make it suitable for many other applications.
|
||||
|
||||
See: [docs/Readme.md](docs/Readme.md) for the library's interface.
|
||||
Since then, the library has been overhauled to offer higher performance, improved visual fidelity, additional features, and quality of life improvements.
|
||||
|
||||
Features:
|
||||
|
||||
* Simple and well documented
|
||||
* Load and unload fonts at any time
|
||||
* Almost entirely configurable and tunable at runtime
|
||||
* Full support for hot-reload
|
||||
* Clear the caches at any time
|
||||
* Robust quality of life features:
|
||||
* Snap positioning to view for better hinting
|
||||
* Tracks text layers
|
||||
* Enforce even-only font sizing (useful for linear zoom)
|
||||
* Push and pop stack for font, font_size, color, view, position, scale, and zoom
|
||||
* Basic (latin) or advanced (harfbuzz) text shaping
|
||||
* All rendering is real-time, with triangulation on the CPU, vertex rendering and texture blitting on the GPU
|
||||
* Can handle thousands of draw text calls with very large or small shapes
|
||||
* 4-Level Regioned Texture Atlas for caching rendered glyphs
|
||||
* Text shape caching
|
||||
* Glyph texture buffer for rendering text with super-sampling to downsample to the atlas or direct to target screen
|
||||
* Super-sample by a font size scalar for sharper glyphs
|
||||
* All caching backed by an optimized 32-bit LRU indexing cache
|
||||
* Provides a backend-agnostic draw list (see [backend](./backend) for usage example)
|
||||
|
||||
Upcoming:
|
||||
|
||||
* Support choosing between top-left or bottom-left coordinate convention (currently bottom-left)
|
||||
* Support for better triangulation
|
||||
* Support for triangulation method selection on a per-font basis
|
||||
* [Reference paper](https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf)
|
||||
* Better support for tuning glyph render sampling
|
||||
* Support for sub-pixel AA
|
||||
* Ability to decide AA method & degree on a per-font basis
|
||||
* Support for Hamza shaper
|
||||
* C-library with ability to set allocator.
|
||||
* Multi-threading supported job queue
|
||||
* Lift heavy-lifting portion of the library's context into a thread context
|
||||
* Synchronize threads by merging their generated layered draw list into a finished draw list for processing on the user's render thread
|
||||
* User defines how thread contexts are distributed for drawing.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [docs/Readme.md](docs/Readme.md) for the library's interface
|
||||
* [docs/guide_backend.md](docs/guide_backend.md) for information on implementing your own backend
|
||||
* [docs/guide_architecture.md](docs/guide_architecture.md) for an in-depth breakdown of significant design decisions and code-paths
|
||||
|
||||
For learning about text shaping & rendering see: [notes](https://github.com/Ed94/TextRendering_Notes)
|
||||
|
||||
## Building
|
||||
|
||||
See [scripts/Readme.md](scripts/Readme.md) for building examples or utilizing the provided backends.
|
||||
|
||||
Currently the scripts provided & the library itself were developed & tested on Windows. There are bash scripts for building on linux (they build on WSL but need additional testing).
|
||||
Currently, the scripts provided & the library itself were developed & tested on Windows. There are bash scripts for building on Linux (they build on WSL but need additional testing).
|
||||
|
||||
The library depends on freetype, harfbuzz, & stb_truetype to build.
|
||||
Note: freetype and harfbuzz could technically be gutted if the user removes their definitions, however they have not been made into a conditional compilation option (yet).
|
||||
The library depends on harfbuzz & stb_truetype to build (a custom stb_truetype package is provided in [thirdparty](./thirdparty/stb/)).
|
||||
Note: harfbuzz could technically be removed if the user removes their definitions, however this hasn't been made into a conditional compilation option yet.
|
||||
|
||||
## Changes from orignal
|
||||
**NOTICE: All library dependency packages are in the "thirdparty" collection of this repository. For their codebase, the user soley has to modify that collection specification for where they would like to put these packages.**
|
||||
|
||||
* Font Parser & Glyph shaper are abstracted to their own warpper interface
|
||||
* ve_fontcache_loadfile not ported (ust use core:os or os2, then call load_font)
|
||||
* Macro defines have been coverted (mostly) to runtime parameters
|
||||
* Support for hot_reloading
|
||||
* Curve quality step interpolation for glyph rendering can be set on a per font basis.
|
||||
## Gallery
|
||||
|
||||
## TODOs
|
||||

|
||||
|
||||
### Additional Features:
|
||||
https://github.com/user-attachments/assets/db8c7725-84dd-48df-9a3f-65605d3ab444
|
||||
|
||||
* Support for freetype (WIP, Currently a mess... and slow)
|
||||
* Add ability to conditionally compile dependencies (so that the user may not need to resolve those packages).
|
||||
* Ability to set a draw transform, viewport and projection
|
||||
* By default the library's position is in unsigned normalized render space
|
||||
* Could implement a similar design to sokol_gp's interface
|
||||
https://github.com/user-attachments/assets/40030308-37db-492d-a196-f830e8a39f3c
|
||||
|
||||
### Optimization:
|
||||
|
||||
* Check if its better to store the glyph vertices if they need to be re-cached to atlas or directly drawn.
|
||||
* Look into setting up multi-threading by giving each thread a context
|
||||
* There is a heavy performance bottleneck in iterating the text/shape/glyphs on the cpu (single-thread) vs the actual rendering *(if doing thousands of drawing commands)*
|
||||
* draw_text can provide in the context a job list per thread for the user to thenk hookup to their own threading solution to handle.
|
||||
* Context would need to be segregated into staged data structures for each thread to utilize
|
||||
* This would need to converge to the singlar draw_list on a per layer basis. The interface expects the user to issue commands single-threaded unless, its assumed the user is going to feed the gpu the commands & data through separate threads as well (not ideal ux).
|
||||
* How the contexts are given jobs should be left up to the user (can recommend a screen quadrant based approach in demo examples)
|
||||
|
||||
Failed Attempts:
|
||||
|
||||
* Attempted to chunk the text to more granular 'shapes' from `draw_list` before doing the actual call to `draw_text_shape`. This lead to a larger performance cost due to the additional iteration across the text string.
|
||||
* Attempted to cache the shape draw_list for future calls. Led to larger performance cost due to additional iteration in the `merge_draw_list`.
|
||||
* The shapes glyphs must still be traversed to identify if the glyph is cached. This arguably could be handled in `shape_text_uncached`, however that would require a significan't amount of refactoring to identify... (and would be more unergonomic when shapers libs are processing the text)
|
||||
https://github.com/user-attachments/assets/0985246b-74f8-4d1c-82d8-053414c44aec
|
||||
|
@@ -12,12 +12,12 @@ Context :: struct {
|
||||
atlas_shader : gfx.Shader,
|
||||
screen_shader : gfx.Shader,
|
||||
|
||||
// 2k x 512, R8
|
||||
// ve.glyph_buffer.(width, height), R8
|
||||
glyph_rt_color : gfx.Image,
|
||||
glyph_rt_depth : gfx.Image,
|
||||
glyph_rt_sampler : gfx.Sampler,
|
||||
|
||||
// 4k x 2k, R8
|
||||
// ve.atlas.(width, height), R8
|
||||
atlas_rt_color : gfx.Image,
|
||||
atlas_rt_depth : gfx.Image,
|
||||
atlas_rt_sampler : gfx.Sampler,
|
||||
@@ -33,7 +33,6 @@ Context :: struct {
|
||||
|
||||
setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index_cap : u64 )
|
||||
{
|
||||
using ctx
|
||||
Attachment_Desc :: gfx.Attachment_Desc
|
||||
Blend_Factor :: gfx.Blend_Factor
|
||||
Blend_Op :: gfx.Blend_Op
|
||||
@@ -60,23 +59,23 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
backend := gfx.query_backend()
|
||||
app_env := glue.environment()
|
||||
|
||||
glyph_shader = gfx.make_shader(render_glyph_shader_desc(backend) )
|
||||
atlas_shader = gfx.make_shader(blit_atlas_shader_desc(backend) )
|
||||
screen_shader = gfx.make_shader(draw_text_shader_desc(backend) )
|
||||
ctx.glyph_shader = gfx.make_shader(render_glyph_shader_desc(backend) )
|
||||
ctx.atlas_shader = gfx.make_shader(blit_atlas_shader_desc(backend) )
|
||||
ctx.screen_shader = gfx.make_shader(draw_text_shader_desc(backend) )
|
||||
|
||||
draw_list_vbuf = gfx.make_buffer( Buffer_Desciption {
|
||||
size = size_of([4]f32) * vert_cap,
|
||||
ctx.draw_list_vbuf = gfx.make_buffer( Buffer_Desciption {
|
||||
size = cast(uint)(size_of([4]f32) * vert_cap),
|
||||
usage = Buffer_Usage.STREAM,
|
||||
type = Buffer_Type.VERTEXBUFFER,
|
||||
})
|
||||
assert( gfx.query_buffer_state( draw_list_vbuf) < Resource_State.FAILED, "Failed to make draw_list_vbuf" )
|
||||
assert( gfx.query_buffer_state( ctx.draw_list_vbuf) < Resource_State.FAILED, "Failed to make draw_list_vbuf" )
|
||||
|
||||
draw_list_ibuf = gfx.make_buffer( Buffer_Desciption {
|
||||
size = size_of(u32) * index_cap,
|
||||
ctx.draw_list_ibuf = gfx.make_buffer( Buffer_Desciption {
|
||||
size = cast(uint)(size_of(u32) * index_cap),
|
||||
usage = Buffer_Usage.STREAM,
|
||||
type = Buffer_Type.INDEXBUFFER,
|
||||
})
|
||||
assert( gfx.query_buffer_state( draw_list_ibuf) < Resource_State.FAILED, "Failed to make draw_list_iubuf" )
|
||||
assert( gfx.query_buffer_state( ctx.draw_list_ibuf) < Resource_State.FAILED, "Failed to make draw_list_iubuf" )
|
||||
|
||||
Image_Filter := Filter.LINEAR
|
||||
|
||||
@@ -84,18 +83,17 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
{
|
||||
vs_layout : Vertex_Layout_State
|
||||
{
|
||||
using vs_layout
|
||||
attrs[ATTR_render_glyph_vs_v_position] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_render_glyph_v_position] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = 0,
|
||||
buffer_index = 0,
|
||||
}
|
||||
attrs[ATTR_render_glyph_vs_v_texture] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_render_glyph_v_texture] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = size_of(ve.Vec2),
|
||||
buffer_index = 0,
|
||||
}
|
||||
buffers[0] = Vertex_Buffer_Layout_State {
|
||||
vs_layout.buffers[0] = Vertex_Buffer_Layout_State {
|
||||
stride = size_of([4]f32),
|
||||
step_func = Vertex_Step.PER_VERTEX
|
||||
}
|
||||
@@ -115,8 +113,8 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
},
|
||||
}
|
||||
|
||||
glyph_pipeline = gfx.make_pipeline({
|
||||
shader = glyph_shader,
|
||||
ctx.glyph_pipeline = gfx.make_pipeline({
|
||||
shader = ctx.glyph_shader,
|
||||
layout = vs_layout,
|
||||
index_type = Vertex_Index_Type.UINT32,
|
||||
colors = {
|
||||
@@ -131,29 +129,29 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
cull_mode = .NONE,
|
||||
sample_count = 1,
|
||||
})
|
||||
assert( gfx.query_pipeline_state(glyph_pipeline) < Resource_State.FAILED, "Failed to make glyph_pipeline" )
|
||||
assert( gfx.query_pipeline_state(ctx.glyph_pipeline) < Resource_State.FAILED, "Failed to make glyph_pipeline" )
|
||||
}
|
||||
|
||||
// glyph_pass
|
||||
{
|
||||
glyph_rt_color = gfx.make_image( Image_Desc {
|
||||
ctx.glyph_rt_color = gfx.make_image( Image_Desc {
|
||||
type = ._2D,
|
||||
render_target = true,
|
||||
width = i32(ve_ctx.glyph_buffer.width),
|
||||
height = i32(ve_ctx.glyph_buffer.height),
|
||||
width = i32(ve_ctx.glyph_buffer.size.x),
|
||||
height = i32(ve_ctx.glyph_buffer.size.y),
|
||||
num_slices = 1,
|
||||
num_mipmaps = 1,
|
||||
usage = .IMMUTABLE,
|
||||
pixel_format = .R8,
|
||||
sample_count = 1,
|
||||
})
|
||||
assert( gfx.query_image_state(glyph_rt_color) < Resource_State.FAILED, "Failed to make glyph_pipeline" )
|
||||
assert( gfx.query_image_state(ctx.glyph_rt_color) < Resource_State.FAILED, "Failed to make glyph_pipeline" )
|
||||
|
||||
glyph_rt_depth = gfx.make_image( Image_Desc {
|
||||
ctx.glyph_rt_depth = gfx.make_image( Image_Desc {
|
||||
type = ._2D,
|
||||
render_target = true,
|
||||
width = i32(ve_ctx.glyph_buffer.width),
|
||||
height = i32(ve_ctx.glyph_buffer.height),
|
||||
width = i32(ve_ctx.glyph_buffer.size.x),
|
||||
height = i32(ve_ctx.glyph_buffer.size.y),
|
||||
num_slices = 1,
|
||||
num_mipmaps = 1,
|
||||
usage = .IMMUTABLE,
|
||||
@@ -161,22 +159,22 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
sample_count = 1,
|
||||
})
|
||||
|
||||
glyph_rt_sampler = gfx.make_sampler( Sampler_Description {
|
||||
ctx.glyph_rt_sampler = gfx.make_sampler( Sampler_Description {
|
||||
min_filter = Image_Filter,
|
||||
mag_filter = Image_Filter,
|
||||
mipmap_filter = Filter.NEAREST,
|
||||
wrap_u = .CLAMP_TO_EDGE,
|
||||
wrap_v = .CLAMP_TO_EDGE,
|
||||
min_lod = -1000.0,
|
||||
max_lod = 1000.0,
|
||||
min_lod = -1.0,
|
||||
max_lod = 1.0,
|
||||
border_color = Border_Color.OPAQUE_BLACK,
|
||||
compare = .NEVER,
|
||||
max_anisotropy = 1,
|
||||
})
|
||||
assert( gfx.query_sampler_state( glyph_rt_sampler) < Resource_State.FAILED, "Failed to make atlas_rt_sampler" )
|
||||
assert( gfx.query_sampler_state( ctx.glyph_rt_sampler) < Resource_State.FAILED, "Failed to make atlas_rt_sampler" )
|
||||
|
||||
color_attach := Attachment_Desc {
|
||||
image = glyph_rt_color,
|
||||
image = ctx.glyph_rt_color,
|
||||
}
|
||||
|
||||
glyph_attachments := gfx.make_attachments({
|
||||
@@ -184,7 +182,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
0 = color_attach,
|
||||
},
|
||||
depth_stencil = {
|
||||
image = glyph_rt_depth,
|
||||
image = ctx.glyph_rt_depth,
|
||||
},
|
||||
})
|
||||
assert( gfx.query_attachments_state(glyph_attachments) < Resource_State.FAILED, "Failed to make glyph_attachments" )
|
||||
@@ -209,7 +207,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
}
|
||||
}
|
||||
|
||||
glyph_pass = gfx.Pass {
|
||||
ctx.glyph_pass = gfx.Pass {
|
||||
action = glyph_action,
|
||||
attachments = glyph_attachments,
|
||||
// label =
|
||||
@@ -220,18 +218,17 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
{
|
||||
vs_layout : Vertex_Layout_State
|
||||
{
|
||||
using vs_layout
|
||||
attrs[ATTR_blit_atlas_vs_v_position] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_blit_atlas_v_position] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = 0,
|
||||
buffer_index = 0,
|
||||
}
|
||||
attrs[ATTR_blit_atlas_vs_v_texture] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_blit_atlas_v_texture] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = size_of(ve.Vec2),
|
||||
buffer_index = 0,
|
||||
}
|
||||
buffers[0] = Vertex_Buffer_Layout_State {
|
||||
vs_layout.buffers[0] = Vertex_Buffer_Layout_State {
|
||||
stride = size_of([4]f32),
|
||||
step_func = Vertex_Step.PER_VERTEX
|
||||
}
|
||||
@@ -251,8 +248,8 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
},
|
||||
}
|
||||
|
||||
atlas_pipeline = gfx.make_pipeline({
|
||||
shader = atlas_shader,
|
||||
ctx.atlas_pipeline = gfx.make_pipeline({
|
||||
shader = ctx.atlas_shader,
|
||||
layout = vs_layout,
|
||||
index_type = Vertex_Index_Type.UINT32,
|
||||
colors = {
|
||||
@@ -271,11 +268,11 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
|
||||
// atlas_pass
|
||||
{
|
||||
atlas_rt_color = gfx.make_image( Image_Desc {
|
||||
ctx.atlas_rt_color = gfx.make_image( Image_Desc {
|
||||
type = ._2D,
|
||||
render_target = true,
|
||||
width = i32(ve_ctx.atlas.width),
|
||||
height = i32(ve_ctx.atlas.height),
|
||||
width = i32(ve_ctx.atlas.size.x),
|
||||
height = i32(ve_ctx.atlas.size.y),
|
||||
num_slices = 1,
|
||||
num_mipmaps = 1,
|
||||
usage = .IMMUTABLE,
|
||||
@@ -284,37 +281,37 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
// TODO(Ed): Setup labels for debug tracing/logging
|
||||
// label =
|
||||
})
|
||||
assert( gfx.query_image_state(atlas_rt_color) < Resource_State.FAILED, "Failed to make atlas_rt_color")
|
||||
assert( gfx.query_image_state(ctx.atlas_rt_color) < Resource_State.FAILED, "Failed to make atlas_rt_color")
|
||||
|
||||
atlas_rt_depth = gfx.make_image( Image_Desc {
|
||||
ctx.atlas_rt_depth = gfx.make_image( Image_Desc {
|
||||
type = ._2D,
|
||||
render_target = true,
|
||||
width = i32(ve_ctx.atlas.width),
|
||||
height = i32(ve_ctx.atlas.height),
|
||||
width = i32(ve_ctx.atlas.size.x),
|
||||
height = i32(ve_ctx.atlas.size.y),
|
||||
num_slices = 1,
|
||||
num_mipmaps = 1,
|
||||
usage = .IMMUTABLE,
|
||||
pixel_format = .DEPTH,
|
||||
sample_count = 1,
|
||||
})
|
||||
assert( gfx.query_image_state(atlas_rt_depth) < Resource_State.FAILED, "Failed to make atlas_rt_depth")
|
||||
assert( gfx.query_image_state(ctx.atlas_rt_depth) < Resource_State.FAILED, "Failed to make atlas_rt_depth")
|
||||
|
||||
atlas_rt_sampler = gfx.make_sampler( Sampler_Description {
|
||||
ctx.atlas_rt_sampler = gfx.make_sampler( Sampler_Description {
|
||||
min_filter = Image_Filter,
|
||||
mag_filter = Image_Filter,
|
||||
mipmap_filter = Filter.NEAREST,
|
||||
wrap_u = .CLAMP_TO_EDGE,
|
||||
wrap_v = .CLAMP_TO_EDGE,
|
||||
min_lod = -1000.0,
|
||||
max_lod = 1000.0,
|
||||
min_lod = -1.0,
|
||||
max_lod = 1.0,
|
||||
border_color = Border_Color.OPAQUE_BLACK,
|
||||
compare = .NEVER,
|
||||
max_anisotropy = 1,
|
||||
})
|
||||
assert( gfx.query_sampler_state( atlas_rt_sampler) < Resource_State.FAILED, "Failed to make atlas_rt_sampler" )
|
||||
assert( gfx.query_sampler_state( ctx.atlas_rt_sampler) < Resource_State.FAILED, "Failed to make atlas_rt_sampler" )
|
||||
|
||||
color_attach := Attachment_Desc {
|
||||
image = atlas_rt_color,
|
||||
image = ctx.atlas_rt_color,
|
||||
}
|
||||
|
||||
atlas_attachments := gfx.make_attachments({
|
||||
@@ -322,7 +319,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
0 = color_attach,
|
||||
},
|
||||
depth_stencil = {
|
||||
image = atlas_rt_depth,
|
||||
image = ctx.atlas_rt_depth,
|
||||
},
|
||||
})
|
||||
assert( gfx.query_attachments_state(atlas_attachments) < Resource_State.FAILED, "Failed to make atlas_attachments")
|
||||
@@ -347,7 +344,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
}
|
||||
}
|
||||
|
||||
atlas_pass = gfx.Pass {
|
||||
ctx.atlas_pass = gfx.Pass {
|
||||
action = atlas_action,
|
||||
attachments = atlas_attachments,
|
||||
}
|
||||
@@ -357,18 +354,17 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
{
|
||||
vs_layout : Vertex_Layout_State
|
||||
{
|
||||
using vs_layout
|
||||
attrs[ATTR_draw_text_vs_v_position] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_draw_text_v_position] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = 0,
|
||||
buffer_index = 0,
|
||||
}
|
||||
attrs[ATTR_draw_text_vs_v_texture] = Vertex_Attribute_State {
|
||||
vs_layout.attrs[ATTR_draw_text_v_texture] = Vertex_Attribute_State {
|
||||
format = Vertex_Format.FLOAT2,
|
||||
offset = size_of(ve.Vec2),
|
||||
buffer_index = 0,
|
||||
}
|
||||
buffers[0] = Vertex_Buffer_Layout_State {
|
||||
vs_layout.buffers[0] = Vertex_Buffer_Layout_State {
|
||||
stride = size_of([4]f32),
|
||||
step_func = Vertex_Step.PER_VERTEX
|
||||
}
|
||||
@@ -388,8 +384,8 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
},
|
||||
}
|
||||
|
||||
screen_pipeline = gfx.make_pipeline({
|
||||
shader = screen_shader,
|
||||
ctx.screen_pipeline = gfx.make_pipeline({
|
||||
shader = ctx.screen_shader,
|
||||
layout = vs_layout,
|
||||
index_type = Vertex_Index_Type.UINT32,
|
||||
colors = {
|
||||
@@ -404,7 +400,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
},
|
||||
cull_mode = .NONE,
|
||||
})
|
||||
assert( gfx.query_pipeline_state(screen_pipeline) < Resource_State.FAILED, "Failed to make screen_pipeline" )
|
||||
assert( gfx.query_pipeline_state(ctx.screen_pipeline) < Resource_State.FAILED, "Failed to make screen_pipeline" )
|
||||
}
|
||||
|
||||
// screen_pass
|
||||
@@ -439,7 +435,7 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
}
|
||||
}
|
||||
|
||||
screen_pass = gfx.Pass {
|
||||
ctx.screen_pass = gfx.Pass {
|
||||
action = screen_action,
|
||||
}
|
||||
}
|
||||
@@ -448,19 +444,17 @@ setup_gfx_objects :: proc( ctx : ^Context, ve_ctx : ^ve.Context, vert_cap, index
|
||||
render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx : Context )
|
||||
{
|
||||
// profile("VEFontCache: render text layer")
|
||||
using ctx
|
||||
|
||||
Bindings :: gfx.Bindings
|
||||
Range :: gfx.Range
|
||||
Shader_Stage :: gfx.Shader_Stage
|
||||
|
||||
vbuf_layer_slice, ibuf_layer_slice, calls_layer_slice := ve.get_draw_list_layer( ve_ctx, optimize_before_returning = true )
|
||||
|
||||
vbuf_ve_range := Range{ raw_data(vbuf_layer_slice), cast(u64) len(vbuf_layer_slice) * size_of(ve.Vertex) }
|
||||
ibuf_ve_range := Range{ raw_data(ibuf_layer_slice), cast(u64) len(ibuf_layer_slice) * size_of(u32) }
|
||||
vbuf_ve_range := Range{ raw_data(vbuf_layer_slice), cast(uint) len(vbuf_layer_slice) * size_of(ve.Vertex) }
|
||||
ibuf_ve_range := Range{ raw_data(ibuf_layer_slice), cast(uint) len(ibuf_layer_slice) * size_of(u32) }
|
||||
|
||||
gfx.append_buffer( draw_list_vbuf, vbuf_ve_range )
|
||||
gfx.append_buffer( draw_list_ibuf, ibuf_ve_range )
|
||||
gfx.append_buffer( ctx.draw_list_vbuf, vbuf_ve_range )
|
||||
gfx.append_buffer( ctx.draw_list_ibuf, ibuf_ve_range )
|
||||
|
||||
ve.flush_draw_list_layer( ve_ctx )
|
||||
|
||||
@@ -484,10 +478,10 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx :
|
||||
continue
|
||||
}
|
||||
|
||||
width := ve_ctx.glyph_buffer.width
|
||||
height := ve_ctx.glyph_buffer.height
|
||||
width := ve_ctx.glyph_buffer.size.x
|
||||
height := ve_ctx.glyph_buffer.size.y
|
||||
|
||||
pass := glyph_pass
|
||||
pass := ctx.glyph_pass
|
||||
if draw_call.clear_before_draw {
|
||||
pass.action.colors[0].load_action = .CLEAR
|
||||
pass.action.colors[0].clear_value.a = 1.0
|
||||
@@ -497,18 +491,17 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx :
|
||||
gfx.apply_viewport( 0,0, width, height, origin_top_left = true )
|
||||
gfx.apply_scissor_rect( 0,0, width, height, origin_top_left = true )
|
||||
|
||||
gfx.apply_pipeline( glyph_pipeline )
|
||||
gfx.apply_pipeline( ctx.glyph_pipeline )
|
||||
|
||||
bindings := Bindings {
|
||||
vertex_buffers = {
|
||||
0 = draw_list_vbuf,
|
||||
0 = ctx.draw_list_vbuf,
|
||||
},
|
||||
vertex_buffer_offsets = {
|
||||
0 = 0,
|
||||
},
|
||||
index_buffer = draw_list_ibuf,
|
||||
index_buffer = ctx.draw_list_ibuf,
|
||||
index_buffer_offset = 0,
|
||||
fs = {},
|
||||
}
|
||||
gfx.apply_bindings( bindings )
|
||||
|
||||
@@ -520,10 +513,10 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx :
|
||||
continue
|
||||
}
|
||||
|
||||
width := ve_ctx.atlas.width
|
||||
height := ve_ctx.atlas.height
|
||||
width := ve_ctx.atlas.size.x
|
||||
height := ve_ctx.atlas.size.y
|
||||
|
||||
pass := atlas_pass
|
||||
pass := ctx.atlas_pass
|
||||
if draw_call.clear_before_draw {
|
||||
pass.action.colors[0].load_action = .CLEAR
|
||||
pass.action.colors[0].clear_value.a = 1.0
|
||||
@@ -533,27 +526,29 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx :
|
||||
gfx.apply_viewport( 0, 0, width, height, origin_top_left = true )
|
||||
gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true )
|
||||
|
||||
gfx.apply_pipeline( atlas_pipeline )
|
||||
gfx.apply_pipeline( ctx.atlas_pipeline )
|
||||
|
||||
fs_uniform := Blit_Atlas_Fs_Params { region = cast(i32) draw_call.region }
|
||||
gfx.apply_uniforms( Shader_Stage.FS, SLOT_blit_atlas_fs_params, Range { & fs_uniform, size_of(Blit_Atlas_Fs_Params) })
|
||||
fs_uniform := Blit_Atlas_Fs_Params {
|
||||
glyph_buffer_size = ve.vec2(ve_ctx.glyph_buffer.size),
|
||||
over_sample = ve_ctx.glyph_buffer.over_sample.x,
|
||||
region = cast(i32) draw_call.region,
|
||||
}
|
||||
gfx.apply_uniforms( UB_blit_atlas_fs_params, Range { & fs_uniform, size_of(Blit_Atlas_Fs_Params) })
|
||||
|
||||
gfx.apply_bindings(Bindings {
|
||||
vertex_buffers = {
|
||||
0 = draw_list_vbuf,
|
||||
0 = ctx.draw_list_vbuf,
|
||||
},
|
||||
vertex_buffer_offsets = {
|
||||
0 = 0,
|
||||
},
|
||||
index_buffer = draw_list_ibuf,
|
||||
index_buffer = ctx.draw_list_ibuf,
|
||||
index_buffer_offset = 0,
|
||||
fs = {
|
||||
images = { SLOT_blit_atlas_src_texture = glyph_rt_color, },
|
||||
samplers = { SLOT_blit_atlas_src_sampler = glyph_rt_sampler, },
|
||||
},
|
||||
images = { IMG_blit_atlas_src_texture = ctx.glyph_rt_color, },
|
||||
samplers = { SMP_blit_atlas_src_sampler = ctx.glyph_rt_sampler, },
|
||||
})
|
||||
|
||||
// 3. Use the atlas to then render the text.
|
||||
// 3. Use the atlas (.Target) or the glyph buffer (.Target_Unchached) to then render the text.
|
||||
case .None, .Target, .Target_Uncached:
|
||||
if num_indices == 0 && ! draw_call.clear_before_draw {
|
||||
continue
|
||||
@@ -561,43 +556,42 @@ render_text_layer :: proc( screen_extent : ve.Vec2, ve_ctx : ^ve.Context, ctx :
|
||||
|
||||
// profile("VEFontCache: draw call: target")
|
||||
|
||||
pass := screen_pass
|
||||
pass := ctx.screen_pass
|
||||
pass.swapchain = glue.swapchain()
|
||||
gfx.begin_pass( pass )
|
||||
|
||||
gfx.apply_viewport( 0, 0, screen_width, screen_height, origin_top_left = true )
|
||||
gfx.apply_scissor_rect( 0, 0, screen_width, screen_height, origin_top_left = true )
|
||||
|
||||
gfx.apply_pipeline( screen_pipeline )
|
||||
gfx.apply_pipeline( ctx.screen_pipeline )
|
||||
|
||||
src_rt := atlas_rt_color
|
||||
src_sampler := atlas_rt_sampler
|
||||
src_rt := ctx.atlas_rt_color
|
||||
src_sampler := ctx.atlas_rt_sampler
|
||||
|
||||
fs_target_uniform := Draw_Text_Fs_Params {
|
||||
down_sample = 0,
|
||||
colour = draw_call.colour,
|
||||
// glyph_buffer_size = glyph_buf_size,
|
||||
over_sample = ve_ctx.glyph_buffer.over_sample.x,
|
||||
colour = draw_call.colour,
|
||||
}
|
||||
|
||||
if draw_call.pass == .Target_Uncached {
|
||||
fs_target_uniform.down_sample = 1
|
||||
src_rt = glyph_rt_color
|
||||
src_sampler = glyph_rt_sampler
|
||||
// fs_target_uniform.over_sample = 1.0
|
||||
src_rt = ctx.glyph_rt_color
|
||||
src_sampler = ctx.glyph_rt_sampler
|
||||
}
|
||||
gfx.apply_uniforms( Shader_Stage.FS, SLOT_draw_text_fs_params, Range { & fs_target_uniform, size_of(Draw_Text_Fs_Params) })
|
||||
gfx.apply_uniforms( UB_draw_text_fs_params, Range { & fs_target_uniform, size_of(Draw_Text_Fs_Params) })
|
||||
|
||||
gfx.apply_bindings(Bindings {
|
||||
vertex_buffers = {
|
||||
0 = draw_list_vbuf,
|
||||
0 = ctx.draw_list_vbuf,
|
||||
},
|
||||
vertex_buffer_offsets = {
|
||||
0 = 0,
|
||||
},
|
||||
index_buffer = draw_list_ibuf,
|
||||
index_buffer = ctx.draw_list_ibuf,
|
||||
index_buffer_offset = 0,
|
||||
fs = {
|
||||
images = { SLOT_draw_text_src_texture = src_rt, },
|
||||
samplers = { SLOT_draw_text_src_sampler = src_sampler, },
|
||||
},
|
||||
images = { IMG_draw_text_src_texture = src_rt, },
|
||||
samplers = { SMP_draw_text_src_sampler = src_sampler, },
|
||||
})
|
||||
}
|
||||
|
||||
|
1778
backend/sokol/blit_atlas.odin
Normal file
1778
backend/sokol/blit_atlas.odin
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
@module blit_atlas
|
||||
// module naming rules are currently dumb with shdc rn...
|
||||
// @module ve_blit_atlas
|
||||
|
||||
@header package ve_sokol
|
||||
@header import sg "thirdparty:sokol/gfx"
|
||||
@@ -11,38 +12,40 @@
|
||||
in vec2 uv;
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform texture2D blit_atlas_src_texture;
|
||||
uniform sampler blit_atlas_src_sampler;
|
||||
layout(binding = 0) uniform texture2D blit_atlas_src_texture;
|
||||
layout(binding = 0) uniform sampler blit_atlas_src_sampler;
|
||||
|
||||
uniform blit_atlas_fs_params {
|
||||
int region;
|
||||
layout(binding = 0) uniform blit_atlas_fs_params {
|
||||
vec2 glyph_buffer_size;
|
||||
float over_sample;
|
||||
int region;
|
||||
};
|
||||
|
||||
float down_sample( vec2 uv, vec2 texture_size )
|
||||
float down_sample_to_texture( vec2 uv, vec2 texture_size )
|
||||
{
|
||||
float down_sample_scale = 1.0f / 4.0f;
|
||||
float down_sample = 1.0f / over_sample;
|
||||
|
||||
float value =
|
||||
texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 0.0f, 0.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 0.0f, 1.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 1.0f, 0.0f ) * texture_size ).x * down_sample_scale
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 1.0f, 1.0f ) * texture_size ).x * down_sample_scale;
|
||||
texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 0.0f, 0.0f ) * texture_size ).x * down_sample
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 0.0f, 1.0f ) * texture_size ).x * down_sample
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 1.0f, 0.0f ) * texture_size ).x * down_sample
|
||||
+ texture(sampler2D( blit_atlas_src_texture, blit_atlas_src_sampler ), uv + vec2( 1.0f, 1.0f ) * texture_size ).x * down_sample;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// TODO(Ed): The original author made these consts, I want to instead expose as uniforms...
|
||||
const vec2 texture_size = 1.0f / vec2( 2048.0f, 512.0f ); // VEFontCache.Context.buffer_width/buffer_height
|
||||
if ( region == 0 || region == 1 || region == 2 )
|
||||
const vec2 texture_size = 1.0f / glyph_buffer_size;
|
||||
if ( region == 0 || region == 1 || region == 2 || region == 4 )
|
||||
{
|
||||
float down_sample_scale = 1.0f / 4.0f;
|
||||
float down_sample = 1.0f / over_sample;
|
||||
|
||||
float alpha =
|
||||
down_sample( uv + vec2( -1.0f, -1.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( 0.5f, -1.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( -1.5f, 0.5f ) * texture_size, texture_size ) * down_sample_scale
|
||||
+ down_sample( uv + vec2( 0.5f, 0.5f ) * texture_size, texture_size ) * down_sample_scale;
|
||||
down_sample_to_texture( uv + vec2( -1.0f, -1.5f ) * texture_size, texture_size ) * down_sample
|
||||
+ down_sample_to_texture( uv + vec2( 0.5f, -1.5f ) * texture_size, texture_size ) * down_sample
|
||||
+ down_sample_to_texture( uv + vec2( -1.5f, 0.5f ) * texture_size, texture_size ) * down_sample
|
||||
+ down_sample_to_texture( uv + vec2( 0.5f, 0.5f ) * texture_size, texture_size ) * down_sample;
|
||||
frag_color = vec4( 1.0f, 1.0f, 1.0f, alpha );
|
||||
}
|
||||
else
|
||||
|
1035
backend/sokol/draw_text.odin
Normal file
1035
backend/sokol/draw_text.odin
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
@module draw_text
|
||||
// module naming rules are currently dumb with shdc rn...
|
||||
// @module ve_draw_text
|
||||
|
||||
@header package ve_sokol
|
||||
@header import sg "thirdparty:sokol/gfx"
|
||||
@@ -23,27 +24,27 @@ void main()
|
||||
in vec2 uv;
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform texture2D draw_text_src_texture;
|
||||
uniform sampler draw_text_src_sampler;
|
||||
layout(binding = 0) uniform texture2D draw_text_src_texture;
|
||||
layout(binding = 0) uniform sampler draw_text_src_sampler;
|
||||
|
||||
uniform draw_text_fs_params {
|
||||
int down_sample;
|
||||
vec4 colour;
|
||||
layout(binding = 0) uniform draw_text_fs_params {
|
||||
vec2 glyph_buffer_size;
|
||||
float over_sample;
|
||||
vec4 colour;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
float alpha = texture(sampler2D( draw_text_src_texture, draw_text_src_sampler ), uv ).x;
|
||||
if ( down_sample == 1 )
|
||||
{
|
||||
// TODO(Ed): The original author made these consts, I want to instead expose as uniforms...
|
||||
const vec2 texture_size = 1.0f / vec2( 2048.0f, 512.0f ); // VEFontCache.Context.buffer_width/buffer_height
|
||||
alpha =
|
||||
(texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( -0.5f, -0.5f) * texture_size ).x * 0.25f)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( -0.5f, 0.5f) * texture_size ).x * 0.25f)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( 0.5f, -0.5f) * texture_size ).x * 0.25f)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( 0.5f, 0.5f) * texture_size ).x * 0.25f);
|
||||
}
|
||||
|
||||
const vec2 texture_size = glyph_buffer_size;
|
||||
const float down_sample = 1.0f / over_sample;
|
||||
|
||||
alpha =
|
||||
(texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( -0.5f, -0.5f) * texture_size ).x * down_sample)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( -0.5f, 0.5f) * texture_size ).x * down_sample)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( 0.5f, -0.5f) * texture_size ).x * down_sample)
|
||||
+ (texture(sampler2D( draw_text_src_texture, draw_text_src_sampler), uv + vec2( 0.5f, 0.5f) * texture_size ).x * down_sample);
|
||||
frag_color = vec4( colour.xyz, colour.a * alpha );
|
||||
}
|
||||
@end
|
||||
|
563
backend/sokol/render_glyph.odin
Normal file
563
backend/sokol/render_glyph.odin
Normal file
@@ -0,0 +1,563 @@
|
||||
package ve_sokol
|
||||
import sg "thirdparty:sokol/gfx"
|
||||
/*
|
||||
#version:1# (machine generated, don't edit!)
|
||||
|
||||
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
|
||||
|
||||
Cmdline:
|
||||
sokol-shdc --input C:\Projects\VEFontCache-Odin\backend\sokol\render_glyph.shdc.glsl --output C:\Projects\VEFontCache-Odin\backend\sokol\render_glyph.odin --slang glsl410:glsl300es:hlsl4:metal_macos:wgsl --format=sokol_odin
|
||||
|
||||
Overview:
|
||||
=========
|
||||
Shader program: 'render_glyph':
|
||||
Get shader desc: render_glyph_shader_desc(sg.query_backend())
|
||||
Vertex Shader: render_glyph_vs
|
||||
Fragment Shader: render_glyph_fs
|
||||
Attributes:
|
||||
ATTR_render_glyph_v_position => 0
|
||||
ATTR_render_glyph_v_texture => 1
|
||||
Bindings:
|
||||
*/
|
||||
ATTR_render_glyph_v_position :: 0
|
||||
ATTR_render_glyph_v_texture :: 1
|
||||
/*
|
||||
#version 410
|
||||
|
||||
layout(location = 0) out vec2 uv;
|
||||
layout(location = 1) in vec2 v_texture;
|
||||
layout(location = 0) in vec2 v_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
uv = vec2(v_texture.x, v_texture.y);
|
||||
gl_Position = vec4(v_position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_vs_source_glsl410 := [235]u8 {
|
||||
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
|
||||
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
|
||||
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,
|
||||
0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,
|
||||
0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x76,0x5f,0x74,
|
||||
0x65,0x78,0x74,0x75,0x72,0x65,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
|
||||
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
|
||||
0x76,0x65,0x63,0x32,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,
|
||||
0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,
|
||||
0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x76,0x5f,
|
||||
0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x2e,0x78,0x2c,0x20,0x76,0x5f,0x74,0x65,0x78,
|
||||
0x74,0x75,0x72,0x65,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,
|
||||
0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,
|
||||
0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x30,0x2c,
|
||||
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
#version 410
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
layout(location = 0) in vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
frag_color = vec4(1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_fs_source_glsl410 := [136]u8 {
|
||||
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
|
||||
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
|
||||
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
|
||||
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
|
||||
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
|
||||
0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,
|
||||
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x31,0x2e,
|
||||
0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
#version 300 es
|
||||
|
||||
out vec2 uv;
|
||||
layout(location = 1) in vec2 v_texture;
|
||||
layout(location = 0) in vec2 v_position;
|
||||
|
||||
void main()
|
||||
{
|
||||
uv = vec2(v_texture.x, v_texture.y);
|
||||
gl_Position = vec4(v_position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_vs_source_glsl300es := [217]u8 {
|
||||
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
|
||||
0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,
|
||||
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
|
||||
0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x76,0x5f,0x74,0x65,0x78,
|
||||
0x74,0x75,0x72,0x65,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,
|
||||
0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,
|
||||
0x63,0x32,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x0a,
|
||||
0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
|
||||
0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x76,0x65,0x63,0x32,0x28,0x76,0x5f,0x74,0x65,
|
||||
0x78,0x74,0x75,0x72,0x65,0x2e,0x78,0x2c,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,
|
||||
0x72,0x65,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,
|
||||
0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x76,0x5f,
|
||||
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,
|
||||
0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
layout(location = 0) out highp vec4 frag_color;
|
||||
in highp vec2 uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
frag_color = vec4(1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_fs_source_glsl300es := [176]u8 {
|
||||
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
|
||||
0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,
|
||||
0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69,
|
||||
0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x6c,
|
||||
0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,
|
||||
0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,
|
||||
0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x69,
|
||||
0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,
|
||||
0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,
|
||||
0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,
|
||||
0x20,0x76,0x65,0x63,0x34,0x28,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
|
||||
}
|
||||
/*
|
||||
static float4 gl_Position;
|
||||
static float2 uv;
|
||||
static float2 v_texture;
|
||||
static float2 v_position;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float2 v_position : TEXCOORD0;
|
||||
float2 v_texture : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 gl_Position : SV_Position;
|
||||
};
|
||||
|
||||
void vert_main()
|
||||
{
|
||||
uv = float2(v_texture.x, 1.0f - v_texture.y);
|
||||
gl_Position = float4(v_position, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
v_texture = stage_input.v_texture;
|
||||
v_position = stage_input.v_position;
|
||||
vert_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.gl_Position = gl_Position;
|
||||
stage_output.uv = uv;
|
||||
return stage_output;
|
||||
}
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_vs_source_hlsl4 := [705]u8 {
|
||||
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,
|
||||
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,
|
||||
0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x3b,0x0a,0x73,0x74,0x61,
|
||||
0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x76,0x5f,0x74,0x65,0x78,
|
||||
0x74,0x75,0x72,0x65,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,
|
||||
0x61,0x74,0x32,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
|
||||
0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
|
||||
0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
|
||||
0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
|
||||
0x6e,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,
|
||||
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,
|
||||
0x75,0x72,0x65,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,
|
||||
0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,
|
||||
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,
|
||||
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x20,0x3a,
|
||||
0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,
|
||||
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,
|
||||
0x6f,0x6e,0x20,0x3a,0x20,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
|
||||
0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x76,0x65,0x72,0x74,0x5f,
|
||||
0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,
|
||||
0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,
|
||||
0x72,0x65,0x2e,0x78,0x2c,0x20,0x31,0x2e,0x30,0x66,0x20,0x2d,0x20,0x76,0x5f,0x74,
|
||||
0x65,0x78,0x74,0x75,0x72,0x65,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,
|
||||
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,
|
||||
0x61,0x74,0x34,0x28,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,
|
||||
0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,
|
||||
0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,
|
||||
0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
|
||||
0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,
|
||||
0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x5f,0x74,
|
||||
0x65,0x78,0x74,0x75,0x72,0x65,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,
|
||||
0x6e,0x70,0x75,0x74,0x2e,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x3b,0x0a,
|
||||
0x20,0x20,0x20,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
|
||||
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x76,0x5f,0x70,
|
||||
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x72,
|
||||
0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,
|
||||
0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,
|
||||
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,
|
||||
0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,
|
||||
0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x67,0x6c,
|
||||
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,
|
||||
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,
|
||||
0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
|
||||
0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
|
||||
0x00,
|
||||
}
|
||||
/*
|
||||
static float4 frag_color;
|
||||
static float2 uv;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 frag_color : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
frag_color = 1.0f.xxxx;
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
uv = stage_input.uv;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.frag_color = frag_color;
|
||||
return stage_output;
|
||||
}
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_fs_source_hlsl4 := [427]u8 {
|
||||
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,
|
||||
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
|
||||
0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x73,0x74,0x72,
|
||||
0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
|
||||
0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
|
||||
0x74,0x32,0x20,0x75,0x76,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,
|
||||
0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,
|
||||
0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,
|
||||
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,
|
||||
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x53,0x56,0x5f,0x54,0x61,
|
||||
0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,
|
||||
0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
|
||||
0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x31,
|
||||
0x2e,0x30,0x66,0x2e,0x78,0x78,0x78,0x78,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,0x50,0x49,
|
||||
0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,
|
||||
0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,
|
||||
0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,
|
||||
0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x73,
|
||||
0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x75,0x76,0x3b,0x0a,0x20,
|
||||
0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,
|
||||
0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
|
||||
0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,
|
||||
0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,
|
||||
0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
|
||||
0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,
|
||||
0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,
|
||||
0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 uv [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 v_position [[attribute(0)]];
|
||||
float2 v_texture [[attribute(1)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.uv = float2(in.v_texture.x, 1.0 - in.v_texture.y);
|
||||
out.gl_Position = float4(in.v_position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_vs_source_metal_macos := [473]u8 {
|
||||
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
|
||||
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
|
||||
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
|
||||
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
|
||||
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
||||
0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,
|
||||
0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
|
||||
0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
|
||||
0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,
|
||||
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
|
||||
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,
|
||||
0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,
|
||||
0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,
|
||||
0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,
|
||||
0x65,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,
|
||||
0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,
|
||||
0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,
|
||||
0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,
|
||||
0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,0x20,
|
||||
0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x69,0x6e,0x2e,0x76,0x5f,0x74,0x65,0x78,0x74,
|
||||
0x75,0x72,0x65,0x2e,0x78,0x2c,0x20,0x31,0x2e,0x30,0x20,0x2d,0x20,0x69,0x6e,0x2e,
|
||||
0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x2e,0x79,0x29,0x3b,0x0a,0x20,0x20,
|
||||
0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
|
||||
0x6e,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x76,0x5f,
|
||||
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,
|
||||
0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
|
||||
0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 frag_color [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0()
|
||||
{
|
||||
main0_out out = {};
|
||||
out.frag_color = float4(1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_fs_source_metal_macos := [238]u8 {
|
||||
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
|
||||
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
|
||||
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
|
||||
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
|
||||
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
||||
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
|
||||
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
|
||||
0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,
|
||||
0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x29,0x0a,0x7b,0x0a,
|
||||
0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,
|
||||
0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
|
||||
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,
|
||||
0x61,0x74,0x34,0x28,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
|
||||
0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
diagnostic(off, derivative_uniformity);
|
||||
|
||||
var<private> uv : vec2f;
|
||||
|
||||
var<private> v_texture : vec2f;
|
||||
|
||||
var<private> v_position : vec2f;
|
||||
|
||||
var<private> gl_Position : vec4f;
|
||||
|
||||
fn main_1() {
|
||||
let x_16 : f32 = v_texture.x;
|
||||
let x_20 : f32 = v_texture.y;
|
||||
uv = vec2f(x_16, (1.0f - x_20));
|
||||
let x_31 : vec2f = v_position;
|
||||
gl_Position = vec4f(x_31.x, x_31.y, 0.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
struct main_out {
|
||||
@location(0)
|
||||
uv_1 : vec2f,
|
||||
@builtin(position)
|
||||
gl_Position : vec4f,
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn main(@location(1) v_texture_param : vec2f, @location(0) v_position_param : vec2f) -> main_out {
|
||||
v_texture = v_texture_param;
|
||||
v_position = v_position_param;
|
||||
main_1();
|
||||
return main_out(uv, gl_Position);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_vs_source_wgsl := [698]u8 {
|
||||
0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,
|
||||
0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,
|
||||
0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,
|
||||
0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,
|
||||
0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,
|
||||
0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,
|
||||
0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,
|
||||
0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,
|
||||
0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,
|
||||
0x65,0x3e,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,
|
||||
0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,
|
||||
0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x31,
|
||||
0x36,0x20,0x3a,0x20,0x66,0x33,0x32,0x20,0x3d,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,
|
||||
0x75,0x72,0x65,0x2e,0x78,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,
|
||||
0x30,0x20,0x3a,0x20,0x66,0x33,0x32,0x20,0x3d,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,
|
||||
0x75,0x72,0x65,0x2e,0x79,0x3b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x76,0x65,
|
||||
0x63,0x32,0x66,0x28,0x78,0x5f,0x31,0x36,0x2c,0x20,0x28,0x31,0x2e,0x30,0x66,0x20,
|
||||
0x2d,0x20,0x78,0x5f,0x32,0x30,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,
|
||||
0x78,0x5f,0x33,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x76,
|
||||
0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,
|
||||
0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x66,
|
||||
0x28,0x78,0x5f,0x33,0x31,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x33,0x31,0x2e,0x79,0x2c,
|
||||
0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x20,0x20,
|
||||
0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,
|
||||
0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,
|
||||
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,
|
||||
0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x0a,0x20,0x20,0x40,0x62,
|
||||
0x75,0x69,0x6c,0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x29,
|
||||
0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,
|
||||
0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x76,0x65,0x72,0x74,
|
||||
0x65,0x78,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,0x61,
|
||||
0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,
|
||||
0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,
|
||||
0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x76,0x5f,
|
||||
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,
|
||||
0x20,0x76,0x65,0x63,0x32,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,
|
||||
0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,
|
||||
0x65,0x20,0x3d,0x20,0x76,0x5f,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x5f,0x70,0x61,
|
||||
0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
|
||||
0x6e,0x20,0x3d,0x20,0x76,0x5f,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x70,
|
||||
0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,
|
||||
0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,
|
||||
0x6f,0x75,0x74,0x28,0x75,0x76,0x2c,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
|
||||
0x69,0x6f,0x6e,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
/*
|
||||
diagnostic(off, derivative_uniformity);
|
||||
|
||||
var<private> frag_color : vec4f;
|
||||
|
||||
var<private> uv : vec2f;
|
||||
|
||||
fn main_1() {
|
||||
frag_color = vec4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
struct main_out {
|
||||
@location(0)
|
||||
frag_color_1 : vec4f,
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main(@location(0) uv_param : vec2f) -> main_out {
|
||||
uv = uv_param;
|
||||
main_1();
|
||||
return main_out(frag_color);
|
||||
}
|
||||
|
||||
*/
|
||||
@(private="file")
|
||||
render_glyph_fs_source_wgsl := [361]u8 {
|
||||
0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,
|
||||
0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,
|
||||
0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,
|
||||
0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
|
||||
0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,
|
||||
0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,
|
||||
0x32,0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,
|
||||
0x20,0x7b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,
|
||||
0x3d,0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x31,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,
|
||||
0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,
|
||||
0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,
|
||||
0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,
|
||||
0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,
|
||||
0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,
|
||||
0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66,0x72,0x61,0x67,0x6d,
|
||||
0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,
|
||||
0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,
|
||||
0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,
|
||||
0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,
|
||||
0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,
|
||||
0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,
|
||||
0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,
|
||||
0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
}
|
||||
render_glyph_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc {
|
||||
desc: sg.Shader_Desc
|
||||
desc.label = "render_glyph_shader"
|
||||
#partial switch backend {
|
||||
case .GLCORE:
|
||||
desc.vertex_func.source = transmute(cstring)&render_glyph_vs_source_glsl410
|
||||
desc.vertex_func.entry = "main"
|
||||
desc.fragment_func.source = transmute(cstring)&render_glyph_fs_source_glsl410
|
||||
desc.fragment_func.entry = "main"
|
||||
desc.attrs[0].base_type = .FLOAT
|
||||
desc.attrs[0].glsl_name = "v_position"
|
||||
desc.attrs[1].base_type = .FLOAT
|
||||
desc.attrs[1].glsl_name = "v_texture"
|
||||
case .GLES3:
|
||||
desc.vertex_func.source = transmute(cstring)&render_glyph_vs_source_glsl300es
|
||||
desc.vertex_func.entry = "main"
|
||||
desc.fragment_func.source = transmute(cstring)&render_glyph_fs_source_glsl300es
|
||||
desc.fragment_func.entry = "main"
|
||||
desc.attrs[0].base_type = .FLOAT
|
||||
desc.attrs[0].glsl_name = "v_position"
|
||||
desc.attrs[1].base_type = .FLOAT
|
||||
desc.attrs[1].glsl_name = "v_texture"
|
||||
case .D3D11:
|
||||
desc.vertex_func.source = transmute(cstring)&render_glyph_vs_source_hlsl4
|
||||
desc.vertex_func.d3d11_target = "vs_4_0"
|
||||
desc.vertex_func.entry = "main"
|
||||
desc.fragment_func.source = transmute(cstring)&render_glyph_fs_source_hlsl4
|
||||
desc.fragment_func.d3d11_target = "ps_4_0"
|
||||
desc.fragment_func.entry = "main"
|
||||
desc.attrs[0].base_type = .FLOAT
|
||||
desc.attrs[0].hlsl_sem_name = "TEXCOORD"
|
||||
desc.attrs[0].hlsl_sem_index = 0
|
||||
desc.attrs[1].base_type = .FLOAT
|
||||
desc.attrs[1].hlsl_sem_name = "TEXCOORD"
|
||||
desc.attrs[1].hlsl_sem_index = 1
|
||||
case .METAL_MACOS:
|
||||
desc.vertex_func.source = transmute(cstring)&render_glyph_vs_source_metal_macos
|
||||
desc.vertex_func.entry = "main0"
|
||||
desc.fragment_func.source = transmute(cstring)&render_glyph_fs_source_metal_macos
|
||||
desc.fragment_func.entry = "main0"
|
||||
desc.attrs[0].base_type = .FLOAT
|
||||
desc.attrs[1].base_type = .FLOAT
|
||||
case .WGPU:
|
||||
desc.vertex_func.source = transmute(cstring)&render_glyph_vs_source_wgsl
|
||||
desc.vertex_func.entry = "main"
|
||||
desc.fragment_func.source = transmute(cstring)&render_glyph_fs_source_wgsl
|
||||
desc.fragment_func.entry = "main"
|
||||
desc.attrs[0].base_type = .FLOAT
|
||||
desc.attrs[1].base_type = .FLOAT
|
||||
}
|
||||
return desc
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
@module render_glyph
|
||||
// module naming rules are currently dumb with shdc rn...
|
||||
// @module render_glyph
|
||||
|
||||
@header package ve_sokol
|
||||
@header import sg "thirdparty:sokol/gfx"
|
||||
|
@@ -1,6 +1,5 @@
|
||||
in vec2 v_position;
|
||||
in vec2 v_texture;
|
||||
// in vec4 v_elem;
|
||||
out vec2 uv;
|
||||
|
||||
void main()
|
||||
|
182
docs/Readme.md
182
docs/Readme.md
@@ -1,23 +1,6 @@
|
||||
# Interface
|
||||
|
||||
Notes
|
||||
---
|
||||
|
||||
The freetype setup is not finished. Specifically due to cache_glyph_freetype not parsing the glyph outline data structure properly.
|
||||
|
||||
Freetype supports specifying a FT_Memory handle which is a pointer to a FT_MemoryRect. This can be used to define an allocator for the parser. Currently this library does not wrap this interface (yet). If using freetype its recommend to update `parser_init` with the necessary changes to wrap the context's backing allocator for freetype to utilize.
|
||||
|
||||
```c
|
||||
struct FT_MemoryRec_
|
||||
{
|
||||
void* user;
|
||||
FT_Alloc_Func alloc;
|
||||
FT_Free_Func free;
|
||||
FT_Realloc_Func realloc;
|
||||
};
|
||||
```
|
||||
|
||||
This library (seems) to perform best if the text commands are fed in 'whitespace aware chunks', where instead of feeding it entire blobs of text, the user identfies "words" in the text and feeding the visible and whitespce chunks derived from this to draw_text as separate calls. It improves the caching of the text shapes. The downside is there has to be a time where the text is parsed into tokens beforehand so that the this iteration does not have to occur continously.
|
||||
## Lifetime
|
||||
|
||||
### startup
|
||||
|
||||
@@ -31,30 +14,68 @@ Much of the data structures within the context struct are not fixed-capacity all
|
||||
|
||||
The library supports being used in a dynamically loaded module. If its hot-reloaded simply make sure to call this procedure with a reference to the backing allocator provided during startup as all dynamic containers tend to lose a proper reference to the allocator's procedure.
|
||||
|
||||
Call `clear_atlas_region_caches` & `clear_shape_cache` to reset the library's shape and glyph cache state to force a re-render.
|
||||
|
||||
### shutdown
|
||||
|
||||
Release resources from the context.
|
||||
|
||||
### configure_snap
|
||||
### clear_atlas_region_caches
|
||||
|
||||
You'll find this used immediately in draw_text it acts as a way to snap the position of the text to the nearest pixel for the width and height specified.
|
||||
Clears the LRU caches of regions A-D of the Atlas & sets their next_idx to 0. Effectively will force a re-cache of all previously rendered glyphs. Shape configuration for the glyph will remain unchanged unless clear_shape_cache is also called.
|
||||
|
||||
If snapping is not desired, set the snap_width and height before calling draw_text to 0.
|
||||
### clear_shape_cache
|
||||
|
||||
### get_cursor_pos
|
||||
Clears the LRU cache of the shaper along with clearing all existing storage entries. Effectively will force a re-cache of previously cached text shapes (Does not recache their rendered glyphs).
|
||||
|
||||
Will provide the current cursor_pos for the resulting text drawn.
|
||||
### load_font
|
||||
|
||||
### set_color
|
||||
Will load an instance of a font. The user needs to load the file's bytes themselves, the font entry (Entry :: struct) will by tracked by the library. The user will be given a font_id which is a direct index for the entry in the tracked array.
|
||||
|
||||
Sets the color to utilize on `Draw_Call`s for FrameBuffer.Target or .Target_Uncached passes
|
||||
### unload_font
|
||||
|
||||
Will free an entry, (parser and shaper resources also freed)
|
||||
|
||||
## Shaping
|
||||
|
||||
Ideally the user should track the shapes themselves in a time-scale beyond the per-frame draw call. This avoids having to do caching/lookups of the shope.
|
||||
|
||||
### shape_text
|
||||
|
||||
Will shape the text using the `shaper_proc` arugment (user overloadable). Shape will be cached by the library.
|
||||
|
||||
### shape_text_uncached
|
||||
|
||||
Will shape the text using the `shaper_proc` arugment (user overloadable).
|
||||
Shape will NOT be cached by the library. Use this if you want to roll your own solution for tracking shapes.
|
||||
|
||||
## Draw list generation
|
||||
|
||||
### draw_text procedures
|
||||
|
||||
There a total of six procedures, 3 for shapes, 3 for text:
|
||||
|
||||
* `draw_shape_normalized_space`
|
||||
* `draw_shape_view_space`
|
||||
* `draw_shape`
|
||||
* `draw_text_normalized_space`
|
||||
* `draw_text_view_space`
|
||||
* `draw_text`
|
||||
|
||||
The normalized space procedures are the `baseline` interface draw procedures. They expect the position, and scale provided to operate with an unsigned normalized space where the bottom left is 0.0, 0.0 and the top right is 1.0, 1.0.
|
||||
|
||||
The view space will normalize the position and scale for the user based on the provided view and zoom. The coordinate system is still unsigned just scaled to the view's size.
|
||||
|
||||
The non-suffix named procedures use the scope stack to derive the position and scale the user provides a relative position and scale for the text that will be adjusted to the scope's view, position, scale, & zoom.
|
||||
|
||||
See the comment above each of the procedures for diagrams.
|
||||
|
||||
### get_draw_list
|
||||
|
||||
Get the enqueded draw_list (vertices, indices, and draw call arrays) in its entirety.
|
||||
By default, if get_draw_list is called, it will first call `optimize_draw_list` to optimize the draw list's calls for the user. If this is undesired, make sure to pass `optimize_before_returning = false` in the arguments.
|
||||
|
||||
### get_draw_list_layer
|
||||
### get_draw_list_layer
|
||||
|
||||
Get the enqueued draw_list for the current "layer".
|
||||
A layer is considered the slice of the `Draw_List`'s content from the last call to `flush_draw_list_layer` onward.
|
||||
@@ -70,6 +91,12 @@ Will clear the draw list and draw layer offsets.
|
||||
|
||||
Will update the draw list layer with the latest offset based on the current lenght of the draw list vertices, indices, and calls arrays.
|
||||
|
||||
## Metrics
|
||||
|
||||
### measure_shape_size
|
||||
|
||||
This provide's the shape size scaled down by the ctx.px_scale to get intended usage size. Size is equivalent to `measure_text_size`.
|
||||
|
||||
### measure_text_size
|
||||
|
||||
Provides a Vec2 the width and height occupied by the provided text string. The y is measured to be the the largest glyph box bounds height of the text. The width is derived from the `end_cursor_pos` field from a `Shaped_Text` entry.
|
||||
@@ -77,3 +104,106 @@ Provides a Vec2 the width and height occupied by the provided text string. The y
|
||||
### get_font_vertical_metrics
|
||||
|
||||
A wrapper for `parser_get_font_vertical_metrics`. Will provide the ascent, descent, and line_gap for a font entry.
|
||||
|
||||
Stuff used by the draw list generation interface or just getters and setters.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### get_font_entry
|
||||
|
||||
Provides the backend Entry for for the given `Font_ID` (passed immutably). If the user desires a mutable reference, just resolve it manually.
|
||||
|
||||
### get_cursor_pos
|
||||
|
||||
Will provide the current cursor_pos for the resulting text drawn.
|
||||
|
||||
### get_normalized_position_scale
|
||||
|
||||
Will normalize the value of the position and scale based on the provided view.
|
||||
Position will also be snapped to the nearest pixel via ceil.
|
||||
Does nothing if view is 1 or 0
|
||||
|
||||
This is used by draw via view relative space procedures to normalize it to the intended space for the render pass.
|
||||
|
||||
### resolve_draw_px_size
|
||||
|
||||
Used to constrain the px_size used in `resolve_zoom_size_scale`.
|
||||
|
||||
The view relative space and scoping stack-based procedures support zoom. When utilizing zoom their is a nasty jitter that will occur if the user smoothly goes across different font sizes because the spacing can drastically change between even and odd font-sizes. This is applied to enforce the font sticks to a specific interval.
|
||||
|
||||
The library uses the context's zoom_px_interval as the reference interval in the draw procedures. It can be set with `set_zoom_px_interval` and the default value is 2.
|
||||
|
||||
### resolve_zoom_size_scale
|
||||
|
||||
Provides a way to get a "zoom" on the font size and scale, similar conceptually to a canvas UX zoom
|
||||
Does nothing when zoom is 1.0
|
||||
|
||||
Uses `resolve_draw_px_size` to constrain which font size is used for the zoom.
|
||||
|
||||
## resolve_px_scalar_size
|
||||
|
||||
Get the target pixel, font_scale, and scale for the given font pixel size, and scalar multiple to apply. (Normalized space with norm_scale)
|
||||
To derived norm_scale use: get_normalized_position_scale or just do (scale * (1 / view))
|
||||
|
||||
This is used within:
|
||||
|
||||
* draw_shape_view_space
|
||||
* draw_text_view_space
|
||||
* draw_shape
|
||||
* draw_text
|
||||
|
||||
### snap_normalized_position_to_view
|
||||
|
||||
Will snap the given position to the nearest pixel via ceil of the given view.
|
||||
Does nothing if view is 1 or 0
|
||||
|
||||
### set_alpha_scalar
|
||||
|
||||
This is an artifact feature of the current shader, it *may* be removed in the future... Increasing the alpha of the colour draw with above 1.0 increases the edge contrast of the glyph shape.
|
||||
|
||||
For the value to be added to the colour, the alph of the text must already be at 1.0 or greater.
|
||||
|
||||
### set_px_scalar
|
||||
|
||||
This another "super-scalar" applied to rendering glyphs. In each draw procedure the following is computed before passing the values to the shaper and draw list generation passes:
|
||||
|
||||
```go
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
```
|
||||
|
||||
Essentially, `ctx.px_scalar` is used to upscale the px_size by its value and then downscale the render target scale back the indended size. Doing so provides better shape positioning and futher improves text hinting. The downside is that small text tends to become more jagged (as its really hitting the limits of of how well the shader can blend those edges at that resolution).
|
||||
|
||||
This will most likely be preserved with future shader upgrades, however it will most likely not be as necessary as it is right now to achieve crisp text.
|
||||
|
||||
### set_zoom_px_interval
|
||||
|
||||
Used with by draw procedures with `resolve_draw_px_size` & `resolve_zoom_size_scale`. Provides the interval to use when constraining the px_size to a specific set of values when using zoom scaling.
|
||||
|
||||
### set_snap_glyph_shape_position
|
||||
|
||||
During the shaping pass, the position of each glyph can be rounded up to the integer to (ussually) allow better hinting.
|
||||
|
||||
### set_snap_glyph_render_height
|
||||
|
||||
During the draw list generation pass, the position of each glyph when blitting to atlas can have teh quad size rounded up to the integer.
|
||||
Can yield better hinting but may significantly stretch the glyphs at small scales.
|
||||
|
||||
## Scope Stack
|
||||
|
||||
These are a set of push & pop pairs of functions that operator ont he context's stack containers. They are used with the draw_shape and draw_text procedures. This mainly for quick scratch usage where the user wants to directly compose a large amount of text without having a UI framework directly handle the text backend.
|
||||
|
||||
* font
|
||||
* font_size
|
||||
* colour: Linear colour.
|
||||
* view: Width and height of the 2D area the text will be drawn within.
|
||||
* position: Uses relative positioning will offset the incoming position by the given amount.
|
||||
* scale: Uses relative scaling, will scale the procedures incoming scale by the given amount.
|
||||
* zoom: Affects scaling, will scale the procedure's incoming font size & scale based on an *UX canvas camera's* notion of it.
|
||||
|
||||
Procedure types:
|
||||
|
||||
* `scope_<stack_option>`: push with a defer pop
|
||||
* `push_<stack_option>`
|
||||
* `pop_<stack_option>`
|
||||
|
234
docs/guide_architecture.md
Normal file
234
docs/guide_architecture.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# Guide: Architecture
|
||||
|
||||
Overview of the package design and code-path layout.
|
||||
|
||||
---
|
||||
|
||||
The purpose of this library is to alleviate four key challenges with one encapsulating package:
|
||||
|
||||
* Font parsing
|
||||
* Text codepoint shaping
|
||||
* Glyph shape triangulation
|
||||
* Glyph draw-list generation
|
||||
|
||||
Shaping text, getting metrics for glyphs, triangulating glyphs, and anti-aliasing their render are expensive operations to perform per frame. Therefore, any compute operations that can be cached, will be.
|
||||
|
||||
There are two cache types used:
|
||||
|
||||
* Shape cache (`Shaped_Text_Cache.state`)
|
||||
* Atlas region cache (`Atlas_Region.state`)
|
||||
|
||||
The shape cache stores all data for a piece of text that will be utilized in a draw call that is not dependent on a specific position & scale (and is faster to lookup vs compute per draw call).
|
||||
The atlas region cache tracks what slots have glyphs rendered to the texture atlas. This essentially caches triangulation and super-sampling computations.
|
||||
|
||||
All caching uses [LRU.odin](../vefontcache/LRU.odin)
|
||||
|
||||
## Code Paths
|
||||
|
||||
### Lifetime
|
||||
|
||||
The library lifetime is straightforward: you have a startup procedure that should be called during your usual app initialization. From there you may either choose to manually shut it down or let the OS clean it up.
|
||||
|
||||
If hot-reload is desired, you just need to call `hot_reload` with the context's backing allocator to refresh the procedure references. After the DLL has been reloaded, these should be the only aspects that have been scrambled.
|
||||
Usually when hot-reloading the library for tuning or major changes, you'd also want to clear the caches. Simply call `clear_atlas_region_caches` & `clear_shape_cache` right after.
|
||||
|
||||
Ideally, there should be zero dynamic allocation on a per-frame basis as long as the reserves for the dynamic containers are never exceeded. It's acceptable if they do exceed as their memory locality is so large their distance in the pages to load into CPU cache won't matter - it just needs to be a low incidence.
|
||||
|
||||
### Shaping Pass
|
||||
|
||||
If using the library's cache, `shaper_shape_text_cached` handles the hashing and lookup. As long as a shape is found, it will not enter the uncached code path. By default, this library uses `shaper_shape_harfbuzz` as the `shape_text_uncached` procedure.
|
||||
|
||||
Shapes are cached using the following parameters to hash a key:
|
||||
|
||||
* font: Font_ID
|
||||
* font_size: f32
|
||||
* the text itself: string
|
||||
|
||||
All shapers fulfill the following interface:
|
||||
|
||||
```odin
|
||||
Shaper_Shape_Text_Uncached_Proc :: #type proc( ctx : ^Shaper_Context,
|
||||
atlas : Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
font : Font_ID,
|
||||
entry : Entry,
|
||||
font_px_Size : f32,
|
||||
font_scale : f32,
|
||||
text_utf8 : string,
|
||||
output : ^Shaped_Text
|
||||
)
|
||||
```
|
||||
|
||||
Which will resolve the output `Shaped_Text`. It has the following definition:
|
||||
|
||||
```odin
|
||||
Shaped_Text :: struct #packed {
|
||||
glyph : [dynamic]Glyph,
|
||||
position : [dynamic]Vec2,
|
||||
visible : [dynamic]i16,
|
||||
atlas_lru_code : [dynamic]Atlas_Key,
|
||||
region_kind : [dynamic]Atlas_Region_Kind,
|
||||
bounds : [dynamic]Range2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
font : Font_ID,
|
||||
px_size : f32,
|
||||
}
|
||||
```
|
||||
|
||||
The result of the shaping process is the glyphs and their positions for the the shape; historically resembling whats known as a *Slug* of prepared text for printing. The end position of where the user's "cursor" would be is recorded which is provided at the end position of the shape. The size of the shape is resolved here as well. If using px_scalar, the shape.size must be downscaled. `measure_shape_size` does the downscaling for the user.
|
||||
|
||||
`visible` tracks which of the glyphs will actually be relevant for the draw_list pass. This is to avoid a conditional jump during the draw list gen pass. When accessing glyph or position during the draw_list gen, they will use visible's relative index.
|
||||
|
||||
The font and px_size is tracked here as well so they user does not need to provide it to the library's interface and related.
|
||||
|
||||
As stated under the main heading of this guide, the the following are within shaped text so that they may be resolved outside of the draw list generation (see: `generate_shape_draw_list`):
|
||||
|
||||
* atlas_lru_code
|
||||
* region_kind
|
||||
* bounds
|
||||
|
||||
These are the same length as the `visible` array, so indexing those will not need to use visibile's relative index.
|
||||
|
||||
`shaper_shape_text_latin` does naive shaping by utilizing the codepoint's kern_advance and detecting newlines.
|
||||
`shaper_shape_harfbuzz` is an actual shaping *engine*. Here is the general idea of how the library utilizes it for shaping:
|
||||
|
||||
1. Reset the state of the hb_buffer
|
||||
2. Determine the line height
|
||||
3. Go through the codepoints: (for each)
|
||||
1. Determine the codepoint's script
|
||||
2. If the script is netural (Uknown, Inherited, or of Common type), the script has not changed, or this is the first codepoint of the shape we can add the codepoint to the buffer.
|
||||
3. Otherwise we will have to start a shaping run if we do encounter a significant script change. After, we can add the codepoint to the post-run-cleared hb_buffer.
|
||||
4. This continues until all codepoints have been processed.
|
||||
4. We do a final shape run after iterating to make sure all codepoints have been processed.
|
||||
5. Set the size of the shape: X is max line width, Y is line height multiplied by the line count.
|
||||
6. Resolve the atlas_lru_code, region_kind, and bounds for all visible glyphs
|
||||
7. Store the font and px_size information.
|
||||
|
||||
The `shape_run` procedure within does the following:
|
||||
|
||||
1. Setup the buffer for the batch
|
||||
2. Have harfbuzz shape the buffer
|
||||
3. Extract glyph infos and positions from the buffer.
|
||||
4. Iterate through all glyphs
|
||||
1. If the hb_glyph cluster is > 0, we need to treat it as the indication of a newline glyph. ***(We update position and skip)***
|
||||
2. Update positioning and other metrics and append output shape's glyph and position.
|
||||
3. If the glyph is visible we append it to shape's visible (harfbuzz must specify it as not .nodef, and parser must identify it as non-empty)
|
||||
5. We update the output.end_cursor_pos with the last position processed by the iteration
|
||||
6. Clear the hb_buffer's contents to prepare for a possible upcoming shape run.
|
||||
|
||||
**Note on shape_run.4: The iteration doesn't preserve tracking the clusters, so that information is lost.**
|
||||
*In the future cluster tracking may be added if its found to be important for high level text features beyond rendering.*
|
||||
|
||||
**Note on shape_run.4.1: Don't know if the glyph signifiying newline should be preserved**
|
||||
|
||||
See [Harfbuzz documentation](https://harfbuzz.github.io) for additional information.
|
||||
|
||||
There are other shapers out there:
|
||||
|
||||
* [hamza](https://github.com/saidwho12/hamza): A notable C library that could be setup with bindings.
|
||||
|
||||
***Note: Monospace fonts may have a much more trivial shaper (however for fonts with ligatures this may not be the case)***
|
||||
***They should only need the kern advance of a single glyph as they're all the same. ligatures (I believe) should preserve this kern advance.***
|
||||
|
||||
### Draw List Generation
|
||||
|
||||
All interface draw text procedures will ultimately call `generate_shape_draw_list`. If the draw procedure is given text, it will call `shaper_shape_text_cached` the text immediately before calling it.
|
||||
|
||||
Its implementation uses a batched-pipeline approach where its goal is to populate three arrays behavings as queues:
|
||||
|
||||
* oversized: For drawing oversized glyphs
|
||||
* to_cache: For glyphs that need triangulation & rendering to glyph buffer then blitting to atlas.
|
||||
* cache: For glyphs that are already cached in the atlas and just need to be blit to the render target.
|
||||
|
||||
And then sent those off to `batch_generate_glyphs_draw_list` for further actual generation to be done. The size of a batch is determined by the capacity of the glyph_buffer's `batch_cache`. This can be set in `glyph_draw_params` for startup.
|
||||
|
||||
`glyph_buffer.glyph_pack` is utilized by both `generate_shape_draw_list` and `batch_generate_glyphs_draw_list` to various computed data in an SOA data structure for the glyphs.
|
||||
|
||||
generate_shape_draw_list outline:
|
||||
|
||||
1. Prepare glyph_pack, oversized, to_cache, cached, and reset the batch cache
|
||||
* `glyph_pack` is resized to to the length of `shape.visible`
|
||||
* The other arrays populated have their reserved set to that length as well (they will not bounds check capacity on append)
|
||||
2. Iterate through the shape.visible and resolve glyph_pack's positions.
|
||||
3. Iterate through shape.visible this time for final region resolution and segregation of glyphs to their appropriate queue.
|
||||
1. If the glyphs assigned region is `.E` its oversized. The `oversample` used for rendering to render target will either be 2x or 1x depending on how huge it is.
|
||||
2. The following glyphs are checked to see if their assigned region has the glyph `cached`.
|
||||
1. If it does, its just appended to cached and marked as seen in the `batch_cache`.
|
||||
2. If its doesn't then a slot is reserved for within the atlas's region and the glyph is appended to `to_cache`.
|
||||
3. For either case the atlas_region_bbox is computed.
|
||||
3. After a batch has been resolved, `batch_generate_glyphs_draw_list` is called.
|
||||
4. If there is an partially filled batch (the usual case), batch_generate_glyphs_draw_list will be called for it.
|
||||
5. The cursor_pos is updated with the shape's end cursor position adjusted for the target space.
|
||||
|
||||
batch_generate_glyphs_draw_list outline:
|
||||
|
||||
The batch is organized into three major stages:
|
||||
|
||||
1. glyph transform & draw quads compute
|
||||
2. glyph_buffer draw list generation (`oversized` & `to_cache`)
|
||||
3. blit-from-atlas to render target draw list generation (`to_cache` & `cached`)
|
||||
|
||||
Glyph transform & draw quads compute does an iteration for each of the 3 arrays.
|
||||
Nearly all the math for all three is done there *except* for `to_cache`, which does its blitting compute in its glyph_buffer draw-list gen pass.
|
||||
|
||||
glyph_buffer draw list generation paths for `oversized` and `to_cache` are unique to each.
|
||||
|
||||
For `oversized`:
|
||||
|
||||
1. Allocate glyph shapes
|
||||
2. Iterate oversized:
|
||||
1. Flush the glyph buffer if flagged todo so (reached glyph allocation limit)
|
||||
2. Call `generate_glyph_pass_draw_list` for trianglation and rendering to buffer.
|
||||
3. blit quad.
|
||||
3. flush the glyph buffer's draw list.
|
||||
4. free glyph shapes
|
||||
|
||||
For `to_cached`:
|
||||
|
||||
1. Allocate glyph shapes
|
||||
2. Iterate to_cache:
|
||||
1. Flush the glyph buffer if flagged todo so (reached glyph allocation limit)
|
||||
2. Compute & blit quads for clearing the atlas region and blitting from the buffer to the atlas.
|
||||
3. Call `generate_glyph_pass_draw_list` for trianglation and rendering to buffer.
|
||||
3. flush the glyph buffer's draw list.
|
||||
4. free glyph shapes
|
||||
5. Do blits from atlas to draw list.
|
||||
|
||||
`cached` only needs to blit from the atlas to the render target.
|
||||
|
||||
`generate_glyph_pass_draw_list`: sets up the draw call for glyph to the glyph buffer. Currently it also handles triangulation as well. For now the shape triangulation is rudimentary and uses triangle fanning. Eventually it would be nice to offer alternative modes that can be specified on a per-font basis.
|
||||
|
||||
`flush_glyph_buffer_draw_list`: Will merge the draw_lists contents of the glyph buffer over to the library's general draw_list, the clear the buffer's draw lists.
|
||||
|
||||
### On Layering
|
||||
|
||||
The base draw list generation pipeline provided by the library allows the user to batch whatever they want into a single "layer".
|
||||
However, the user most likely would want take into consideration: font instances, font size, colors; these are things that may benefit from having shared locality during a layer batch. Overlaping text benefits from the user to handle the ordering via layers.
|
||||
|
||||
Layers (so far) are just a set of offssets tracked by the library's `Context.draw_layer` struct. When `flush_draw_list_layer` is called, the offsets are set to the current length of the draw list. This allows the rendering backend to retrieve the latest set of vertices, indices, and calls to render on a per-layer basis with: `get_draw_list_layer`.
|
||||
|
||||
Importantly, this leads to the following pattern when enuquing a layer to render:
|
||||
|
||||
1. Begin render pass
|
||||
2. For codepath that will deal with text layers
|
||||
1. Process user-level code-path that calls the draw text interface, populating the draw list layer (usually a for loop)
|
||||
2. After iteration on the layer is complete, render the text layer
|
||||
1. grab the draw list layer
|
||||
2. flush the layer so the draw list offsets are reset
|
||||
3. Repeat until all layers for the codepath are exhausted.
|
||||
|
||||
There is consideration to instead explicitly have a draw list with more contextual information of the start and end of each layer. So that batching can be orchestrated in an isolated section of their pipeline.
|
||||
|
||||
This would involve just tracking *slices* of thier draw-list that represents layers:
|
||||
|
||||
```odin
|
||||
Draw_List_Layer :: struct {
|
||||
vertices : []Vertex,
|
||||
indices : []u32,
|
||||
calls : []Draw_Call,
|
||||
}
|
||||
```
|
||||
|
||||
Eventually the library may provide this since adding that feature is relatively cheap and and a low line-count addition to the interface.
|
||||
There should be little to no perfomrance loss from doing so as the iteration size is two large of a surface area to matter (so its just pipeline ergonomics).
|
68
docs/guide_backend.md
Normal file
68
docs/guide_backend.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Guide: Backend
|
||||
|
||||
The end-user needs to adapt this library to hook into their own codebase. For reference, they can check the [examples](../examples/) and [backend](../backend/) directories for working code that demonstrates what this guide covers.
|
||||
|
||||
When rendering text, users need to handle two main aspects: the text to draw and its "layering". Similar to UIs, text should be drawn in layer batches, where each layer can represent a pass with arbitrary distinctions from other layers.
|
||||
|
||||
The following components are required:
|
||||
|
||||
* Vertex and Index Buffers for glyph meshes
|
||||
* Glyph shader for rendering glyphs to the glyph buffer
|
||||
* Atlas shader for blitting upscaled glyph quads from the glyph buffer to an atlas region slot (downsampled)
|
||||
* "Screen or Target" shader for blitting glyph quads from the atlas to a render target or swapchain
|
||||
* The glyph, atlas, and target image buffers
|
||||
|
||||
Currently, the library doesn't support sub-pixel AA, so we're only rendering to R8 images.
|
||||
|
||||
## Rendering Passes
|
||||
|
||||
There are four passes that need to be handled when rendering a draw list:
|
||||
|
||||
* Glyph: Rendering a glyph mesh to the glyph buffer
|
||||
* Atlas: Blitting a glyph quad from the glyph buffer to an atlas slot
|
||||
* Target: Blitting from the atlas image to the target image
|
||||
* Target_Uncached: Blitting from the glyph buffer image to the target image
|
||||
|
||||
The Target & Target_Uncached passes can technically be handled in the same case. The user just needs to swap between using the atlas image and the glyph buffer image. This is how the backend_sokol.odin's `render_text_layer` has these passes set up.
|
||||
|
||||
## Vertex Buffer Layout
|
||||
|
||||
The vertex buffer has the following layout for all passes:
|
||||
|
||||
* `[2]f32` for positions
|
||||
* `[2]f32` for texture coords (Offset is naturally `[2]f32`)
|
||||
* Total stride: `[4]f32`
|
||||
|
||||
---
|
||||
|
||||
The index buffer is a simple u32 stream.
|
||||
|
||||
For quad mesh layout details, see `blit_quad` in [draw.odin](../vefontcache/draw.odin).
|
||||
|
||||
For glyph shape triangulation meshes, the library currently only uses a triangle fanning technique, implemented in `fill_path_via_fan_triangulation` within [draw.odin](../vefontcache/draw.odin). Eventually, the library will support other modes on a per-font basis.
|
||||
|
||||
## UV Coordinate Conventions (GLSL vs HLSL)
|
||||
|
||||
DirectX, Metal, and Vulkan consider the top-left corner as (0, 0), where the Y axis increases downward (traditional screenspace). This library follows OpenGL's convention, where (0, 0) is at the bottom-left (Y goes up).
|
||||
|
||||
Adjust the UV coordinates in your shader accordingly:
|
||||
|
||||
```c
|
||||
#if !OpenGL
|
||||
uv = vec2(v_texture.x, 1.0 - v_texture.y);
|
||||
#else
|
||||
uv = vec2(v_texture.x, v_texture.y);
|
||||
#endif
|
||||
```
|
||||
|
||||
Eventually, the library will support both conventions as a comp-time conditional.
|
||||
|
||||
## Retrieving & Processing the layer
|
||||
|
||||
`get_draw_list_layer` will provide the layer's vertex, index, and draw call slices. Unless the default is overwritten, it will call `optimize_draw_list` before returning the slices (profile to see whats better for your use case).
|
||||
Once those are retrived, call `flush_draw_list_layer` to update the layer offsets tracked by the library's `Context`.
|
||||
|
||||
The vertex and index slices just needed to be appended to your backend's vertex and index buffers.
|
||||
The draw calls need to be iterated with a switch statement for the aforementioned pass types. Within the case you can construct the enqueue the passes.
|
||||
|
||||
---
|
@@ -42,7 +42,7 @@ FONT_LARGEST_PIXEL_SIZE :: 400
|
||||
FONT_SIZE_INTERVAL :: 2
|
||||
|
||||
FONT_DEFAULT :: Font_ID { "" }
|
||||
FONT_DEFAULT_SIZEZ :: 12.0
|
||||
FONT_DEFAULT_SIZE :: 12.0
|
||||
|
||||
FONT_LOAD_USE_DEFAULT_SIZE :: -1
|
||||
FONT_LOAD_GEN_ID :: ""
|
||||
@@ -56,16 +56,17 @@ Font_ID :: struct {
|
||||
label : string,
|
||||
}
|
||||
|
||||
FontDef :: struct {
|
||||
Font_Entry :: struct {
|
||||
path_file : string,
|
||||
data : []byte,
|
||||
default_size : i32,
|
||||
size_table : [FONT_LARGEST_PIXEL_SIZE / FONT_SIZE_INTERVAL] ve.Font_ID,
|
||||
ve_id : ve.Font_ID,
|
||||
}
|
||||
|
||||
Demo_Context :: struct {
|
||||
ve_ctx : ve.Context,
|
||||
render_ctx : ve_sokol.Context,
|
||||
font_ids : map[string]FontDef,
|
||||
font_ids : map[string]Font_Entry,
|
||||
|
||||
// Values between 1, & -1 on Y axis
|
||||
mouse_scroll : Vec2,
|
||||
@@ -106,7 +107,7 @@ font_load :: proc(path_file : string,
|
||||
font_data, read_succeded : = os.read_entire_file( path_file )
|
||||
assert( bool(read_succeded), fmt.tprintf("Failed to read font file for: %v", path_file) )
|
||||
font_data_size := cast(i32) len(font_data)
|
||||
font_firacode : Font_ID
|
||||
font_firacode : Font_ID
|
||||
|
||||
|
||||
desired_id := desired_id
|
||||
@@ -115,24 +116,20 @@ font_firacode : Font_ID
|
||||
desired_id = file_name_from_path(path_file)
|
||||
}
|
||||
|
||||
demo_ctx.font_ids[desired_id] = FontDef {}
|
||||
demo_ctx.font_ids[desired_id] = Font_Entry {}
|
||||
def := & demo_ctx.font_ids[desired_id]
|
||||
|
||||
default_size := default_size
|
||||
if default_size < 0 {
|
||||
default_size = FONT_DEFAULT_SIZEZ
|
||||
default_size = FONT_DEFAULT_SIZE
|
||||
}
|
||||
|
||||
error : ve.Load_Font_Error
|
||||
def.path_file = path_file
|
||||
def.default_size = default_size
|
||||
|
||||
for font_size : i32 = clamp( FONT_SIZE_INTERVAL, 2, FONT_SIZE_INTERVAL ); font_size <= FONT_LARGEST_PIXEL_SIZE; font_size += FONT_SIZE_INTERVAL
|
||||
{
|
||||
id := (font_size / FONT_SIZE_INTERVAL) + (font_size % FONT_SIZE_INTERVAL)
|
||||
ve_id := & def.size_table[id - 1]
|
||||
ve_ret_id := ve.load_font( & demo_ctx.ve_ctx, desired_id, font_data, f32(font_size), curve_quality )
|
||||
(ve_id^) = ve_ret_id
|
||||
}
|
||||
def.data = font_data
|
||||
def.ve_id, error = ve.load_font( & demo_ctx.ve_ctx, desired_id, font_data, curve_quality )
|
||||
assert(error == .None)
|
||||
|
||||
fid := Font_ID { desired_id }
|
||||
return fid
|
||||
@@ -140,84 +137,42 @@ font_firacode : Font_ID
|
||||
|
||||
Font_Use_Default_Size :: f32(0.0)
|
||||
|
||||
font_resolve_draw_id :: proc( id : Font_ID, size := Font_Use_Default_Size ) -> ( ve_id : ve.Font_ID, resolved_size : i32 )
|
||||
{
|
||||
def := demo_ctx.font_ids[ id.label ]
|
||||
size := size == 0.0 ? f32(def.default_size) : size
|
||||
even_size := math.round(size * (1.0 / f32(FONT_SIZE_INTERVAL))) * f32(FONT_SIZE_INTERVAL)
|
||||
resolved_size = clamp( i32( even_size), 2, FONT_LARGEST_PIXEL_SIZE )
|
||||
|
||||
id := (resolved_size / FONT_SIZE_INTERVAL) + (resolved_size % FONT_SIZE_INTERVAL)
|
||||
ve_id = def.size_table[ id - 1 ]
|
||||
return
|
||||
}
|
||||
|
||||
measure_text_size :: proc( text : string, font : Font_ID, font_size := Font_Use_Default_Size, spacing : f32 ) -> Vec2
|
||||
{
|
||||
ve_id, size := font_resolve_draw_id( font, font_size )
|
||||
measured := ve.measure_text_size( & demo_ctx.ve_ctx, ve_id, text )
|
||||
def := demo_ctx.font_ids[ font.label ]
|
||||
measured := ve.measure_text_size( & demo_ctx.ve_ctx, def.ve_id, font_size, text )
|
||||
return measured
|
||||
}
|
||||
|
||||
get_font_vertical_metrics :: #force_inline proc ( font : Font_ID, font_size := Font_Use_Default_Size ) -> ( ascent, descent, line_gap : f32 )
|
||||
{
|
||||
ve_id, size := font_resolve_draw_id( font, font_size )
|
||||
ascent, descent, line_gap = ve.get_font_vertical_metrics( & demo_ctx.ve_ctx, ve_id )
|
||||
def := demo_ctx.font_ids[ font.label ]
|
||||
ascent, descent, line_gap = ve.get_font_vertical_metrics( demo_ctx.ve_ctx, def.ve_id, font_size )
|
||||
return
|
||||
}
|
||||
|
||||
// Draw text using a string and normalized render coordinates
|
||||
draw_text_string_pos_norm :: proc( content : string, id : Font_ID, size : f32, pos : Vec2, color := COLOR_WHITE, scale : f32 = 1.0 )
|
||||
draw_text :: proc( content : string, font : Font_ID, pos : Vec2, size : f32 = 0.0, color := COLOR_WHITE, scale : f32 = 1.0, zoom : f32 = 1.0 )
|
||||
{
|
||||
width := demo_ctx.screen_size.x
|
||||
height := demo_ctx.screen_size.y
|
||||
color_norm := normalize_rgba8(color)
|
||||
def := demo_ctx.font_ids[ font.label ]
|
||||
size := size >= 2.0 ? size : f32(def.default_size)
|
||||
|
||||
ve_id, resolved_size := font_resolve_draw_id( id, size )
|
||||
color_norm := normalize_rgba8(color)
|
||||
|
||||
ve.set_colour( & demo_ctx.ve_ctx, color_norm )
|
||||
ve.draw_text( & demo_ctx.ve_ctx, ve_id, content, pos, Vec2{1 / width, 1 / height} * scale )
|
||||
resolved_size, zoom_scale := ve.resolve_zoom_size_scale( zoom, size, scale, 2, 2, 999.0, demo_ctx.screen_size )
|
||||
snapped_pos := ve.snap_normalized_position_to_view( pos, demo_ctx.screen_size )
|
||||
norm_scale := zoom_scale * (1 / demo_ctx.screen_size)
|
||||
ve.draw_text_normalized_space( & demo_ctx.ve_ctx,
|
||||
def.ve_id,
|
||||
resolved_size,
|
||||
color_norm,
|
||||
snapped_pos,
|
||||
norm_scale,
|
||||
content
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Draw text using a string and extent-based screen coordinates
|
||||
draw_text_string_pos_extent :: proc( content : string, id : Font_ID, size : f32, pos : Vec2, color := COLOR_WHITE ) {
|
||||
render_pos := pos + demo_ctx.screen_size * 0.5
|
||||
normalized_pos := render_pos * (1.0 / demo_ctx.screen_size)
|
||||
draw_text_string_pos_norm( content, id, size, normalized_pos, color )
|
||||
}
|
||||
|
||||
// Adapt the draw_text_string_pos_extent_zoomed procedure
|
||||
draw_text_zoomed_norm :: proc(content : string, id : Font_ID, size : f32, pos : Vec2, zoom : f32, color := COLOR_WHITE)
|
||||
{
|
||||
screen_size := demo_ctx.screen_size
|
||||
screen_scale := Vec2{1.0 / screen_size.x, 1.0 / screen_size.y}
|
||||
zoom_adjust_size := size * zoom
|
||||
|
||||
// Over-sample font-size
|
||||
|
||||
zoom_adjust_size *= OVER_SAMPLE_ZOOM
|
||||
|
||||
ve_id, resolved_size := font_resolve_draw_id(id, zoom_adjust_size)
|
||||
|
||||
text_scale := screen_scale
|
||||
{
|
||||
f32_resolved_size := f32(resolved_size)
|
||||
diff_scalar := 1 + (zoom_adjust_size - f32_resolved_size) / f32_resolved_size
|
||||
text_scale = diff_scalar * screen_scale
|
||||
text_scale.x = clamp(text_scale.x, 0, 1)
|
||||
text_scale.y = clamp(text_scale.y, 0, 1)
|
||||
}
|
||||
|
||||
// Down-sample back
|
||||
text_scale /= OVER_SAMPLE_ZOOM
|
||||
|
||||
color_norm := normalize_rgba8(color)
|
||||
ve.set_colour(&demo_ctx.ve_ctx, color_norm)
|
||||
ve.draw_text(&demo_ctx.ve_ctx, ve_id, content, pos, text_scale)
|
||||
}
|
||||
|
||||
sokol_app_alloc :: proc "c" ( size : u64, user_data : rawptr ) -> rawptr {
|
||||
sokol_app_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr {
|
||||
context = runtime.default_context()
|
||||
block, error := mem.alloc( int(size), allocator = context.allocator )
|
||||
assert(error == .None, "sokol_app allocation failed")
|
||||
@@ -229,7 +184,7 @@ sokol_app_free :: proc "c" ( data : rawptr, user_data : rawptr ) {
|
||||
free(data, allocator = context.allocator)
|
||||
}
|
||||
|
||||
sokol_gfx_alloc :: proc "c" ( size : u64, user_data : rawptr ) -> rawptr {
|
||||
sokol_gfx_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr {
|
||||
context = runtime.default_context()
|
||||
block, error := mem.alloc( int(size), allocator = context.allocator )
|
||||
assert(error == .None, "sokol_gfx allocation failed")
|
||||
@@ -271,11 +226,23 @@ init :: proc "c" ()
|
||||
case .DUMMY: fmt.println(">> using dummy backend")
|
||||
}
|
||||
|
||||
ve.startup( & demo_ctx.ve_ctx, .STB_TrueType, allocator = context.allocator, snap_shape_position = false, use_advanced_text_shaper = true )
|
||||
ve_sokol.setup_gfx_objects( & demo_ctx.render_ctx, & demo_ctx.ve_ctx, vert_cap = 1024 * 1024, index_cap = 1024 * 1024 )
|
||||
glyph_draw_opts := ve.Init_Glyph_Draw_Params_Default
|
||||
glyph_draw_opts.snap_glyph_width = false
|
||||
glyph_draw_opts.snap_glyph_height = false
|
||||
|
||||
shaper_opts := ve.Init_Shaper_Params_Default
|
||||
shaper_opts.snap_glyph_position = true
|
||||
|
||||
ve.startup( & demo_ctx.ve_ctx, .STB_TrueType, allocator = context.allocator,
|
||||
glyph_draw_params = glyph_draw_opts,
|
||||
shaper_params = shaper_opts,
|
||||
px_scalar = 1.4,
|
||||
alpha_sharpen = 0.1,
|
||||
)
|
||||
ve_sokol.setup_gfx_objects( & demo_ctx.render_ctx, & demo_ctx.ve_ctx, vert_cap = 256 * 1024, index_cap = 512 * 1024 )
|
||||
|
||||
error : mem.Allocator_Error
|
||||
demo_ctx.font_ids, error = make( map[string]FontDef, 256 )
|
||||
demo_ctx.font_ids, error = make( map[string]Font_Entry, 256 )
|
||||
assert( error == .None, "Failed to allocate demo_ctx.font_ids" )
|
||||
|
||||
path_sawarabi_mincho := strings.concatenate({ PATH_FONTS, "SawarabiMincho-Regular.ttf" })
|
||||
@@ -294,26 +261,25 @@ init :: proc "c" ()
|
||||
path_noto_sans_jp_reg := strings.concatenate({ PATH_FONTS, "NotoSansJP-Regular.otf" })
|
||||
path_firacode := strings.concatenate({ PATH_FONTS, "FiraCode-Regular.ttf" })
|
||||
|
||||
using demo_ctx
|
||||
font_logo = font_load(path_sawarabi_mincho, 330.0, "SawarabiMincho", 6 )
|
||||
font_title = font_load(path_open_sans, 92.0, "OpenSans", 12 )
|
||||
font_print = font_load(path_noto_sans_jp, 19.0, "NotoSansJP")
|
||||
font_mono = font_load(path_ubuntu_mono, 21.0, "UbuntuMono")
|
||||
font_small = font_load(path_roboto, 10.0, "Roboto")
|
||||
font_demo_sans = font_load(path_open_sans, 18.0, "OpenSans")
|
||||
font_demo_serif = font_load(path_bitter, 18.0, "Bitter")
|
||||
font_demo_script = font_load(path_dancing_script, 22.0, "DancingScript")
|
||||
font_demo_mono = font_load(path_nova_mono, 18.0, "NovaMono")
|
||||
font_demo_chinese = font_load(path_noto_serif_sc, 24.0, "NotoSerifSC")
|
||||
font_demo_japanese = font_load(path_sawarabi_mincho, 24.0, "SawarabiMincho")
|
||||
font_demo_korean = font_load(path_nanum_pen_script, 36.0, "NanumPenScript")
|
||||
font_demo_thai = font_load(path_krub, 24.0, "Krub")
|
||||
font_demo_arabic = font_load(path_tajawal, 24.0, "Tajawal")
|
||||
font_demo_hebrew = font_load(path_david_libre, 22.0, "DavidLibre")
|
||||
font_demo_raincode = font_load(path_noto_sans_jp_reg, 20.0, "NotoSansJPRegular")
|
||||
font_demo_grid2 = font_load(path_noto_serif_sc, 54.0, "NotoSerifSC")
|
||||
font_demo_grid3 = font_load(path_bitter, 44.0, "Bitter")
|
||||
font_firacode = font_load(path_firacode, 16.0, "FiraCode", 12 )
|
||||
demo_ctx.font_logo = font_load(path_sawarabi_mincho, 150.0, "SawarabiMincho", 18 )
|
||||
demo_ctx.font_print = font_load(path_noto_sans_jp, 19.0, "NotoSansJP")
|
||||
demo_ctx.font_mono = font_load(path_ubuntu_mono, 21.0, "UbuntuMono")
|
||||
demo_ctx.font_small = font_load(path_roboto, 10.0, "Roboto")
|
||||
demo_ctx.font_demo_sans = font_load(path_open_sans, 18.0, "OpenSans", 6)
|
||||
demo_ctx.font_demo_serif = font_load(path_bitter, 18.0, "Bitter")
|
||||
demo_ctx.font_demo_script = font_load(path_dancing_script, 22.0, "DancingScript")
|
||||
demo_ctx.font_demo_mono = font_load(path_nova_mono, 18.0, "NovaMono")
|
||||
demo_ctx.font_demo_chinese = font_load(path_noto_serif_sc, 24.0, "NotoSerifSC")
|
||||
demo_ctx.font_demo_japanese = font_load(path_sawarabi_mincho, 24.0, "SawarabiMincho")
|
||||
demo_ctx.font_demo_korean = font_load(path_nanum_pen_script, 36.0, "NanumPenScript")
|
||||
demo_ctx.font_demo_thai = font_load(path_krub, 24.0, "Krub")
|
||||
demo_ctx.font_demo_arabic = font_load(path_tajawal, 24.0, "Tajawal")
|
||||
demo_ctx.font_demo_hebrew = font_load(path_david_libre, 22.0, "DavidLibre")
|
||||
demo_ctx.font_demo_raincode = font_load(path_noto_sans_jp_reg, 20.0, "NotoSansJPRegular")
|
||||
demo_ctx.font_title = demo_ctx.font_demo_sans
|
||||
demo_ctx.font_demo_grid2 = demo_ctx.font_demo_chinese
|
||||
demo_ctx.font_demo_grid3 = demo_ctx.font_demo_serif
|
||||
demo_ctx.font_firacode = font_load(path_firacode, 16.0, "FiraCode", 12 )
|
||||
}
|
||||
|
||||
event :: proc "c" (sokol_event : ^app.Event)
|
||||
@@ -335,10 +301,8 @@ frame :: proc "c" ()
|
||||
gfx.begin_pass({ action = pass_action, swapchain = glue.swapchain() })
|
||||
gfx.end_pass()
|
||||
{
|
||||
ve.configure_snap( & demo_ctx.ve_ctx, u32(demo_ctx.screen_size.x), u32(demo_ctx.screen_size.y) )
|
||||
ve.set_colour( & demo_ctx.ve_ctx, ve.Colour { 1.0, 1.0, 1.0, 1.0 })
|
||||
|
||||
using demo_ctx
|
||||
// ve.configure_snap( & demo_ctx.ve_ctx, u32(demo_ctx.screen_size.x), u32(demo_ctx.screen_size.y) )
|
||||
// ve.set_colour( & demo_ctx.ve_ctx, ve.Colour { 1.0, 1.0, 1.0, 1.0 })
|
||||
|
||||
// Smooth scrolling implementation
|
||||
@static demo_autoscroll := false
|
||||
@@ -350,7 +314,7 @@ frame :: proc "c" ()
|
||||
|
||||
frame_duration := cast(f32) app.frame_duration()
|
||||
|
||||
scroll_velocity += mouse_scroll.y * 0.05
|
||||
scroll_velocity += demo_ctx.mouse_scroll.y * 0.035
|
||||
mouse_down_pos = -1.0
|
||||
substep_dt := frame_duration / 4.0
|
||||
for _ in 0 ..< 4 {
|
||||
@@ -360,14 +324,16 @@ frame :: proc "c" ()
|
||||
if demo_autoscroll {
|
||||
current_scroll += 0.05 * frame_duration
|
||||
}
|
||||
mouse_scroll = {} // Reset mouse scroll
|
||||
demo_ctx.mouse_scroll = {} // Reset mouse scroll
|
||||
|
||||
// Clamp scroll value if needed
|
||||
current_scroll = clamp(current_scroll, 0, 6.1) // Adjust max value as needed
|
||||
|
||||
// Frametime display
|
||||
frametime_text := fmt.tprintf("Frametime %v", frame_duration)
|
||||
draw_text_string_pos_norm(frametime_text, font_title, 0, {0.0, 0.0}, COLOR_WHITE)
|
||||
draw_text(frametime_text, demo_ctx.font_title, {0.0, 0.0}, size = 30)
|
||||
|
||||
// Below is content based on the original demo from the C++ library.
|
||||
|
||||
if current_scroll < 1.5 {
|
||||
intro := `Ça va! Everything here is rendered using VE Font Cache, a single header-only library designed for game engines.
|
||||
@@ -382,9 +348,9 @@ It aims to:
|
||||
• Support cached text shaping with HarfBuzz with simple Latin-style fallback.
|
||||
• Load and unload fonts at any time.`
|
||||
|
||||
draw_text_string_pos_norm("ゑ", font_logo, 330, {0.4, current_scroll}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("VEFontCache Demo", font_title, 92, {0.2, current_scroll - 0.1}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(intro, font_print, 19, {0.2, current_scroll - 0.14}, COLOR_WHITE)
|
||||
draw_text("ゑ", demo_ctx.font_logo, { 0.4, current_scroll }, size = 200, scale = 2.0)
|
||||
draw_text("VEFontCache Demo", demo_ctx.font_title, { 0.2, current_scroll - 0.1 }, size = 92)
|
||||
draw_text(intro, demo_ctx.font_print, { 0.2, current_scroll - 0.14 }, size = 19)
|
||||
}
|
||||
|
||||
section_start : f32 = 0.42
|
||||
@@ -427,10 +393,10 @@ Glyphs are first rendered to an intermediate 2k x 512px R8 texture. This allows
|
||||
4 x 4 = 16x supersampling, and 8 Region C glyphs similarly. A simple 16-tap box downsample shader is then used to blit from this
|
||||
intermediate texture to the final atlas location.`
|
||||
|
||||
draw_text_string_pos_norm("How it works", font_title, 92, {0.2, current_scroll - (section_start + 0.06)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(how_it_works, font_print, 19, {0.2, current_scroll - (section_start + 0.1)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(caching_strategy, demo_ctx.font_mono, 21, {0.28, current_scroll - (section_start + 0.32)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(how_it_works2, font_print, 19, {0.2, current_scroll - (section_start + 0.82)}, COLOR_WHITE)
|
||||
draw_text("How it works", demo_ctx.font_title, { 0.2, current_scroll - (section_start + 0.06) }, size = 92)
|
||||
draw_text(how_it_works, demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.1) }, size = 19)
|
||||
draw_text(caching_strategy, demo_ctx.font_mono, { 0.28, current_scroll - (section_start + 0.32) }, size = 21)
|
||||
draw_text(how_it_works2, demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.82) }, size = 19)
|
||||
}
|
||||
|
||||
// Showcase section
|
||||
@@ -441,49 +407,49 @@ intermediate texture to the final atlas location.`
|
||||
incididunt ut labore et dolore magna aliqua. Est ullamcorper eget nulla facilisi
|
||||
etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
|
||||
draw_text_string_pos_norm("Showcase", font_title, 92, {0.2, current_scroll - (section_start + 0.2)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("This is a showcase demonstrating different hb_font categories and languages.", font_print, 19, {0.2, current_scroll - (section_start + 0.24)}, COLOR_WHITE)
|
||||
draw_text("Showcase", demo_ctx.font_title, { 0.2, current_scroll - (section_start + 0.2) }, size = 92)
|
||||
draw_text("This is a showcase demonstrating different hb_font categories and languages.", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.24) }, size = 19)
|
||||
|
||||
draw_text_string_pos_norm("Sans serif", font_print, 19, {0.2, current_scroll - (section_start + 0.28)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(font_family_test, font_demo_sans, 18, {0.3, current_scroll - (section_start + 0.28)}, COLOR_WHITE)
|
||||
draw_text("Sans serif", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.28) }, size = 19)
|
||||
draw_text(font_family_test, demo_ctx.font_demo_sans, { 0.3, current_scroll - (section_start + 0.28) }, size = 18)
|
||||
|
||||
draw_text_string_pos_norm("Serif", font_print, 19, {0.2, current_scroll - (section_start + 0.36)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(font_family_test, font_demo_serif, 18, {0.3, current_scroll - (section_start + 0.36)}, COLOR_WHITE)
|
||||
draw_text("Serif", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.36) }, size = 19)
|
||||
draw_text(font_family_test, demo_ctx.font_demo_serif, { 0.3, current_scroll - (section_start + 0.36) }, size = 18)
|
||||
|
||||
draw_text_string_pos_norm("Script", font_print, 19, {0.2, current_scroll - (section_start + 0.44)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(font_family_test, font_demo_script, 22, {0.3, current_scroll - (section_start + 0.44)}, COLOR_WHITE)
|
||||
draw_text("Script", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.44) }, size = 19)
|
||||
draw_text(font_family_test, demo_ctx.font_demo_script, { 0.3, current_scroll - (section_start + 0.44) }, size = 22)
|
||||
|
||||
draw_text_string_pos_norm("Monospace", font_print, 19, {0.2, current_scroll - (section_start + 0.52)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(font_family_test, font_demo_mono, 18, {0.3, current_scroll - (section_start + 0.52)}, COLOR_WHITE)
|
||||
draw_text("Monospace", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.52) }, size = 19)
|
||||
draw_text(font_family_test, demo_ctx.font_demo_mono, { 0.3, current_scroll - (section_start + 0.52) }, size = 22)
|
||||
|
||||
draw_text_string_pos_norm("Small", font_print, 19, {0.2, current_scroll - (section_start + 0.60)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm(font_family_test, font_small, 10, {0.3, current_scroll - (section_start + 0.60)}, COLOR_WHITE)
|
||||
draw_text("Small", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.60) }, size = 19)
|
||||
draw_text(font_family_test, demo_ctx.font_small, { 0.3, current_scroll - (section_start + 0.60) }, size = 10)
|
||||
|
||||
draw_text_string_pos_norm("Greek", font_print, 19, {0.2, current_scroll - (section_start + 0.72)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("Ήταν απλώς θέμα χρόνου.", font_demo_sans, 18, {0.3, current_scroll - (section_start + 0.72)}, COLOR_WHITE)
|
||||
draw_text("Greek", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.72) }, size = 19)
|
||||
draw_text("Ήταν απλώς θέμα χρόνου.", demo_ctx.font_demo_sans, { 0.3, current_scroll - (section_start + 0.72) }, size = 18)
|
||||
|
||||
draw_text_string_pos_norm("Vietnamese", font_print, 19, {0.2, current_scroll - (section_start + 0.76)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("Bầu trời trong xanh thăm thẳm, không một gợn mây.", font_demo_sans, 18, {0.3, current_scroll - (section_start + 0.76)}, COLOR_WHITE)
|
||||
draw_text("Vietnamese", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.76) }, size = 19)
|
||||
draw_text("Bầu trời trong xanh thăm thẳm, không một gợn mây.", demo_ctx.font_demo_sans, { 0.3, current_scroll - (section_start + 0.76) }, size = 18)
|
||||
|
||||
draw_text_string_pos_norm("Thai", font_print, 19, {0.2, current_scroll - (section_start + 0.80)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("การเดินทางขากลับคงจะเหงา", font_demo_thai, 24, {0.3, current_scroll - (section_start + 0.80)}, COLOR_WHITE)
|
||||
draw_text("Thai", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.80) }, size = 19)
|
||||
draw_text("การเดินทางขากลับคงจะเหงา", demo_ctx.font_demo_thai, { 0.3, current_scroll - (section_start + 0.80) }, size = 24)
|
||||
|
||||
draw_text_string_pos_norm("Chinese", font_print, 19, {0.2, current_scroll - (section_start + 0.84)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("床前明月光 疑是地上霜 举头望明月 低头思故乡", font_demo_chinese, 24, {0.3, current_scroll - (section_start + 0.84)}, COLOR_WHITE)
|
||||
draw_text("Chinese", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.84) }, size = 19)
|
||||
draw_text("床前明月光 疑是地上霜 举头望明月 低头思故乡", demo_ctx.font_demo_chinese, {0.3, current_scroll - (section_start + 0.84) }, size = 24)
|
||||
|
||||
draw_text_string_pos_norm("Japanese", font_print, 19, {0.2, current_scroll - (section_start + 0.88)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("ぎょしょうとナレズシの研究 モンスーン・アジアの食事文化", font_demo_japanese, 24, {0.3, current_scroll - (section_start + 0.88)}, COLOR_WHITE)
|
||||
draw_text("Japanese", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.88) }, size = 19)
|
||||
draw_text("ぎょしょうとナレズシの研究 モンスーン・アジアの食事文化", demo_ctx.font_demo_japanese, { 0.3, current_scroll - (section_start + 0.88) }, size = 24)
|
||||
|
||||
draw_text_string_pos_norm("Korean", font_print, 19, {0.2, current_scroll - (section_start + 0.92)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("그들의 장비와 기구는 모두 살아 있다.", font_demo_korean, 36, {0.3, current_scroll - (section_start + 0.92)}, COLOR_WHITE)
|
||||
draw_text("Korean", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.92) }, size = 19)
|
||||
draw_text("그들의 장비와 기구는 모두 살아 있다.", demo_ctx.font_demo_korean, { 0.3, current_scroll - (section_start + 0.92) }, size = 36)
|
||||
|
||||
draw_text_string_pos_norm("Needs harfbuzz to work:", font_print, 14, {0.2, current_scroll - (section_start + 0.96)}, COLOR_WHITE)
|
||||
draw_text("Needs harfbuzz to work:", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 0.96)}, size = 14)
|
||||
|
||||
draw_text_string_pos_norm("Arabic", font_print, 19, {0.2, current_scroll - (section_start + 1.00)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("حب السماء لا تمطر غير الأحلام.", font_demo_arabic, 24, {0.3, current_scroll - (section_start + 1.00)}, COLOR_WHITE)
|
||||
draw_text("Arabic", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 1.00) }, size = 19)
|
||||
draw_text("حب السماء لا تمطر غير الأحلام.", demo_ctx.font_demo_arabic, { 0.3, current_scroll - (section_start + 1.00) }, size = 24)
|
||||
|
||||
draw_text_string_pos_norm("Hebrew", font_print, 19, {0.2, current_scroll - (section_start + 1.04)}, COLOR_WHITE)
|
||||
draw_text_string_pos_norm("אז הגיע הלילה של כוכב השביט הראשון.", font_demo_hebrew, 22, {0.3, current_scroll - (section_start + 1.04)}, COLOR_WHITE)
|
||||
draw_text("Hebrew", demo_ctx.font_print, { 0.2, current_scroll - (section_start + 1.04) }, size = 19)
|
||||
draw_text("אז הגיע הלילה של כוכב השביט הראשון.", demo_ctx.font_demo_hebrew, { 0.3, current_scroll - (section_start + 1.04) }, size = 22)
|
||||
}
|
||||
|
||||
// Zoom Test
|
||||
@@ -521,20 +487,18 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
zoom_info_y := current_scroll - (section_start + 0.10)
|
||||
zoomed_text_y := current_scroll - (section_start + 0.30) + math.sin(zoom_time) * 0.02
|
||||
|
||||
draw_text_string_pos_norm("Zoom Test", font_title, 92, {0.2, title_y}, COLOR_WHITE)
|
||||
draw_text("Zoom Test", demo_ctx.font_title, { 0.2, title_y }, size = 92)
|
||||
|
||||
zoomed_text_base_size : f32 = 12.0
|
||||
zoom_adjust_size := zoomed_text_base_size * current_zoom
|
||||
ve_id, resolved_size := font_resolve_draw_id( font_firacode, zoom_adjust_size * OVER_SAMPLE_ZOOM )
|
||||
resolved_size, _ := ve.resolve_zoom_size_scale(current_zoom, zoomed_text_base_size, 1.0, 2, 2, 999.0, demo_ctx.screen_size)
|
||||
current_zoom_text := fmt.tprintf("Current Zoom : %.2f x\nCurrent Resolved Size: %v px", current_zoom, resolved_size )
|
||||
draw_text_string_pos_norm(current_zoom_text, font_firacode, 19, {0.2, zoom_info_y}, COLOR_WHITE)
|
||||
draw_text(current_zoom_text, demo_ctx.font_firacode, { 0.2, zoom_info_y })
|
||||
|
||||
ve.configure_snap( & demo_ctx.ve_ctx, u32(0), u32(0) )
|
||||
|
||||
size := measure_text_size( zoom_text, font_firacode, zoomed_text_base_size, 0 ) * current_zoom
|
||||
size := measure_text_size( zoom_text, demo_ctx.font_firacode, zoomed_text_base_size, 0 ) * current_zoom
|
||||
x_offset := (size.x / demo_ctx.screen_size.x) * 0.5
|
||||
zoomed_text_pos := Vec2 { 0.5 - x_offset, zoomed_text_y }
|
||||
draw_text_zoomed_norm(zoom_text, font_firacode, zoomed_text_base_size, zoomed_text_pos, current_zoom, COLOR_WHITE)
|
||||
draw_text(zoom_text, demo_ctx.font_firacode, zoomed_text_pos, size = zoomed_text_base_size, zoom = current_zoom)
|
||||
}
|
||||
|
||||
// Raincode Demo
|
||||
@@ -543,7 +507,7 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
if current_scroll > section_start && current_scroll < section_end
|
||||
{
|
||||
GRID_W :: 80
|
||||
GRID_H :: 50
|
||||
GRID_H :: 45
|
||||
NUM_RAINDROPS :: GRID_W / 3
|
||||
|
||||
@static init_grid := false
|
||||
@@ -557,7 +521,7 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Z", "T", "H", "E", "|", "¦", "日",
|
||||
"ハ", "ミ", "ヒ", "ー", "ウ", "シ", "ナ", "モ", "ニ", "サ", "ワ", "ツ", "オ", "リ", "ア", "ホ", "テ", "マ",
|
||||
"ケ", "メ", "エ", "カ", "キ", "ム", "ユ", "ラ", "セ", "ネ", "ス", "ツ", "タ", "ヌ", "ヘ", ":", "・", ".",
|
||||
"\"", "=", "*", "+", "-", "<", ">", "ç", "リ", "ク", "コ", "チ", "ヤ", "ル", "ン", "C", "O", "D"
|
||||
"\"", "=", "*", "+", "-", "<", ">", "ç", "リ", "ク", "コ", "チ", "ヤ", "ル", "ン", "C", "O", "D",
|
||||
}
|
||||
|
||||
if !init_grid {
|
||||
@@ -586,7 +550,7 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
}
|
||||
|
||||
// Draw grid
|
||||
draw_text_string_pos_norm("Raincode demo", font_title, 92, { 0.2, current_scroll - (section_start + 0.2) }, COLOR_WHITE)
|
||||
draw_text("Raincode demo", demo_ctx.font_title, { 0.2, current_scroll - (section_start + 0.2) }, size = 92)
|
||||
for y in 0 ..< GRID_H do for x in 0 ..< GRID_W
|
||||
{
|
||||
pos_x := 0.2 + f32(x) * 0.007
|
||||
@@ -603,16 +567,14 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
if code_colour.a == 0 do continue
|
||||
}
|
||||
|
||||
draw_text_string_pos_norm(codes[grid[y * GRID_W + x]], font_demo_raincode, 20, {pos_x, pos_y}, code_colour)
|
||||
draw_text(codes[grid[y * GRID_W + x]], demo_ctx.font_demo_raincode, { pos_x, pos_y }, size = 20, color = code_colour)
|
||||
}
|
||||
|
||||
ve.set_colour(&ve_ctx, {1.0, 1.0, 1.0, 1.0})
|
||||
}
|
||||
|
||||
// Cache pressure test
|
||||
section_start = 5.3
|
||||
section_end = 6.2
|
||||
if current_scroll > section_start && current_scroll < section_end && true
|
||||
if current_scroll > section_start && current_scroll < section_end
|
||||
{
|
||||
GRID_W :: 30
|
||||
GRID_H :: 15
|
||||
@@ -629,7 +591,7 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
@static fixed_timestep_passed : f32 = 0.0
|
||||
|
||||
fixed_timestep_passed += frame_duration
|
||||
fixed_timestep := f32(1.0 / 30.0)
|
||||
fixed_timestep := f32(1.0 / 120.0)
|
||||
for fixed_timestep_passed > fixed_timestep
|
||||
{
|
||||
rotate_current = (rotate_current + 1) % 4
|
||||
@@ -673,28 +635,28 @@ etiam dignissim diam quis enim. Convallis convallis tellus id interdum.`
|
||||
}
|
||||
|
||||
// Draw grid
|
||||
draw_text_string_pos_norm("Cache pressure test", font_title, 92, {0.2, current_scroll - (section_start + 0.2)}, COLOR_WHITE)
|
||||
draw_text("Cache pressure test (throttled to 120 hz)", demo_ctx.font_title, { 0.2, current_scroll - (section_start + 0.2) }, size = 72)
|
||||
for y in 0..< GRID_H do for x in 0 ..< GRID_W
|
||||
{
|
||||
posx := 0.2 + f32(x) * 0.02
|
||||
posy := current_scroll - (section_start + 0.24 + f32(y) * 0.025)
|
||||
c := [5]u8{}
|
||||
codepoint_to_utf8(c[:], grid[ y * GRID_W + x ])
|
||||
draw_text_string_pos_norm(string( c[:] ), font_demo_chinese, 24, {posx, posy}, COLOR_WHITE)
|
||||
draw_text(string( c[:] ), demo_ctx.font_demo_chinese, { posx, posy }, size = 24)
|
||||
}
|
||||
for y in 0 ..< GRID2_H do for x in 0 ..< GRID2_W {
|
||||
posx := 0.2 + f32(x) * 0.03
|
||||
posy := current_scroll - (section_start + 0.66 + f32(y) * 0.052)
|
||||
c := [5]u8{}
|
||||
codepoint_to_utf8(c[:], grid2[ y * GRID2_W + x ])
|
||||
draw_text_string_pos_norm(string( c[:] ), font_demo_grid2, 54, {posx, posy}, COLOR_WHITE)
|
||||
draw_text(string( c[:] ), demo_ctx.font_demo_grid2, { posx, posy }, size = 54)
|
||||
}
|
||||
for y in 0 ..< GRID3_H do for x in 0 ..< GRID3_W {
|
||||
posx := 0.45 + f32(x) * 0.02
|
||||
posy := current_scroll - (section_start + 0.64 + f32(y) * 0.034)
|
||||
posy := current_scroll - (section_start + 0.64 + f32(y) * 0.04)
|
||||
c := [5]u8{}
|
||||
codepoint_to_utf8( c[:], grid3[ y * GRID3_W + x ])
|
||||
draw_text_string_pos_norm(string( c[:] ), font_demo_grid3, 44, {posx, posy}, COLOR_WHITE)
|
||||
draw_text(string( c[:] ), demo_ctx.font_demo_grid3, { posx, posy }, size = 44)
|
||||
}
|
||||
}
|
||||
|
||||
|
31
ols.json
31
ols.json
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
|
||||
"odin_command": "odin.exe",
|
||||
"collections": [
|
||||
{
|
||||
"name": "backend",
|
||||
"path": "./backend"
|
||||
},
|
||||
{
|
||||
"name": "examples",
|
||||
"path": "./sectr"
|
||||
},
|
||||
{
|
||||
"name": "thirdparty",
|
||||
"path": "./thirdparty"
|
||||
}
|
||||
],
|
||||
"enable_document_symbols": true,
|
||||
"enable_fake_methods": true,
|
||||
"enable_format": false,
|
||||
"enable_hover": true,
|
||||
"enable_semantic_tokens": false,
|
||||
"enable_snippets": false,
|
||||
"enable_references": true,
|
||||
"thread_pool_count": 10,
|
||||
"enable_inlay_hints": true,
|
||||
"enable_procedure_context": true,
|
||||
"enable_procedure_snippet": false,
|
||||
"verbose": true,
|
||||
"disable_parser_errors": true
|
||||
}
|
@@ -12,11 +12,15 @@ Its assumed the user has Odin installed and exposed to the OS enviornment's PATH
|
||||
|
||||
#### Note on dependency packages
|
||||
|
||||
All dependencies are cloned directly into a created thirdparty directory.
|
||||
A custom version of the vendor:stb/truetype is maintained by this library:
|
||||
|
||||
* Added ability to set the stb_truetype allocator for `STBTT_MALLOC` and `STBTT_FREE`.
|
||||
* Changed procedure signatures to pass the font_info struct by immutable ptr (#by_ptr) when the C equivalent has their parameter as `const*`.
|
||||
|
||||
All other dependencies are provided directly into the thirdparty directory. However they can be cloned from their corresponding github repos:
|
||||
|
||||
[harfbuzz](https://github.com/Ed94/odin_harfbuzz) is configured to pull & build the C++ library, it will use the MSVC toolchain (you can change it to use meson instead of preferred).
|
||||
[freetype](https://github.com/Ed94/odin-freetype) package has pre-built .lib files for windows (debug/release).
|
||||
[sokol](https://github.com/floooh/sokol) built using `build_sokol_library.ps`.
|
||||
[sokol](https://github.com/floooh/sokol) built using `build_sokol_library.ps1`.
|
||||
[sokol-tools](https://github.com/floooh/sokol-tools) used by `compile_sokol_shaders.ps1` to compile the glsl files into odin files for the sokol backend.
|
||||
|
||||
### build_sokol_library.ps1
|
||||
@@ -41,23 +45,27 @@ Will run `Launch-VsDevShell.ps1` for the user to populate the shell with its env
|
||||
|
||||
A few helper functions to utilize powerhsell & github repos as package management.
|
||||
|
||||
|
||||
### odin_compiler_defs.ps1
|
||||
|
||||
Just variable declarations based on flags used with the odin compiler's CLI.
|
||||
|
||||
# Linux
|
||||
# Mac & Linux
|
||||
|
||||
Essentially equivalent scripts from the PS scripts used on windows were ported to bash. Tested in WSL ubuntu image (so far).
|
||||
Essentially equivalent scripts from the PS scripts used on windows were ported to bash. Tested in WSL ubuntu image for Linux, and a github action workflow for MacOS.
|
||||
|
||||
Build sokol manually if not using a fresh clone.
|
||||
|
||||
#### Note on dependency packages
|
||||
|
||||
Some dependencies are cloned directly into a created thirdparty directory.
|
||||
All other dependencies are provided directly into the thirdparty directory. However they can be cloned from their corresponding github repos:
|
||||
|
||||
[harfbuzz](https://github.com/Ed94/odin_harfbuzz) is configured to pull & build the C++ library, it will use the MSVC toolchain (you can change it to use meson instead of preferred).
|
||||
[freetype](https://github.com/Ed94/odin-freetype) package does not come with linux binaries.
|
||||
[sokol](https://github.com/floooh/sokol) built using `build_sokol_library.ps`.
|
||||
[sokol-tools](https://github.com/floooh/sokol-tools) used by `compile_sokol_shaders.ps1` to compile the glsl files into odin files for the sokol backend.
|
||||
[harfbuzz](https://github.com/Ed94/odin_harfbuzz) is configured to pull & build the C++ library, it will use the gcc toolchain (you can change it to use meson instead of preferred).
|
||||
|
||||
* On MacOS, harbuzz imports through system:harfbuzz instead as there is an issue with importing via relative directories.
|
||||
* Use for example `brew install harfbuzz`
|
||||
|
||||
[sokol](https://github.com/floooh/sokol) built using `build_sokol_library.sh`.
|
||||
[sokol-tools](https://github.com/floooh/sokol-tools) used by `compile_sokol_shaders.sh` to compile the glsl files into odin files for the sokol backend.
|
||||
|
||||
Caveats:
|
||||
|
||||
|
@@ -32,19 +32,18 @@ elseif ( $IsWindows ) {
|
||||
write-host "Core Count - Physical: $CoreCount_Physical Logical: $CoreCount_Logical"
|
||||
#endregion CPU_Info
|
||||
|
||||
$url_freetype = 'https://github.com/Ed94/odin-freetype.git'
|
||||
# $url_freetype = 'https://github.com/Ed94/odin-freetype.git'
|
||||
$url_harfbuzz = 'https://github.com/Ed94/harfbuzz-odin.git'
|
||||
$url_sokol = 'https://github.com/floooh/sokol-odin.git'
|
||||
$url_sokol_tools = 'https://github.com/floooh/sokol-tools-bin.git'
|
||||
|
||||
$path_freetype = join-path $path_thirdparty 'freetype'
|
||||
# $path_freetype = join-path $path_thirdparty 'freetype'
|
||||
$path_harfbuzz = join-path $path_thirdparty 'harfbuzz'
|
||||
$path_sokol = join-path $path_thirdparty 'sokol'
|
||||
$path_sokol_tools = join-path $path_thirdparty 'sokol-tools'
|
||||
|
||||
$sokol_build_clibs_command = join-path $path_scripts 'build_sokol_library.ps1'
|
||||
|
||||
clone-gitrepo $path_freetype $url_freetype
|
||||
clone-gitrepo $path_sokol_tools $url_sokol_tools
|
||||
|
||||
Update-GitRepo -path $path_sokol -url $url_sokol -build_command $sokol_build_clibs_command
|
||||
@@ -67,6 +66,15 @@ push-location $path_thirdparty
|
||||
}
|
||||
pop-location
|
||||
|
||||
$path_stb_truetype = join-path $path_thirdparty 'stb\src'
|
||||
|
||||
push-location $path_stb_truetype
|
||||
$devshell = Join-Path $PSScriptRoot 'helpers/devshell.ps1'
|
||||
. $devshell -arch amd64
|
||||
|
||||
& .\build.bat
|
||||
pop-location
|
||||
|
||||
$odin_compiler_defs = join-path $PSScriptRoot 'helpers/odin_compiler_defs.ps1'
|
||||
. $odin_compiler_defs
|
||||
|
||||
@@ -94,11 +102,11 @@ function build-SokolBackendDemo
|
||||
# $build_args += $flag_micro_architecture_native
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
# $build_args += $flag_optimize_none
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
$build_args += $falg_optimize_aggressive
|
||||
# $build_args += $flag_debug
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
# $build_args += ($flag_extra_linker_flags + $linker_args )
|
||||
@@ -111,6 +119,8 @@ function build-SokolBackendDemo
|
||||
# $build_args += $flag_sanitize_address
|
||||
# $build_args += $flag_sanitize_memory
|
||||
|
||||
Write-Host $build_args
|
||||
|
||||
Invoke-WithColorCodedOutput { & $odin_compiler $build_args }
|
||||
}
|
||||
build-SokolBackendDemo
|
||||
|
@@ -42,20 +42,20 @@ else
|
||||
fi
|
||||
echo "Core Count - Physical: $CoreCount_Physical Logical: $CoreCount_Logical"
|
||||
|
||||
url_freetype='https://github.com/Ed94/odin-freetype.git'
|
||||
# url_freetype='https://github.com/Ed94/odin-freetype.git'
|
||||
url_harfbuzz='https://github.com/Ed94/harfbuzz-odin.git'
|
||||
url_sokol='https://github.com/floooh/sokol-odin.git'
|
||||
url_sokol_tools='https://github.com/floooh/sokol-tools-bin.git'
|
||||
|
||||
path_freetype="$path_thirdparty/freetype"
|
||||
# path_freetype="$path_thirdparty/freetype"
|
||||
path_harfbuzz="$path_thirdparty/harfbuzz"
|
||||
path_sokol="$path_thirdparty/sokol"
|
||||
path_sokol_tools="$path_thirdparty/sokol-tools"
|
||||
|
||||
sokol_build_clibs_command="$path_scripts/build_sokol_library.sh"
|
||||
|
||||
clone_gitrepo "$path_freetype" "$url_freetype"
|
||||
clone_gitrepo "$path_sokol_tools" "$url_sokol_tools"
|
||||
# clone_git_repo "$path_freetype" "$url_freetype"
|
||||
clone_git_repo "$path_sokol_tools" "$url_sokol_tools"
|
||||
|
||||
update_git_repo "$path_sokol" "$url_sokol" "$sokol_build_clibs_command"
|
||||
update_git_repo "$path_harfbuzz" "$url_harfbuzz" "./scripts/build.sh"
|
||||
@@ -81,6 +81,12 @@ pushd "$path_thirdparty" > /dev/null
|
||||
fi
|
||||
popd > /dev/null
|
||||
|
||||
path_stb_truetype="$path_thirdparty/stb/src"
|
||||
|
||||
pushd "$path_stb_truetype" > /dev/null
|
||||
make
|
||||
popd > /dev/null
|
||||
|
||||
source "$(dirname "$0")/helpers/odin_compiler_defs.sh"
|
||||
|
||||
pkg_collection_backend="backend=$path_backend"
|
||||
|
@@ -66,7 +66,6 @@ case "$OS" in
|
||||
Darwin*)
|
||||
echo "Detected macOS operating system"
|
||||
echo "Running macOS build script..."
|
||||
ls -al
|
||||
./build_clibs_macos.sh
|
||||
;;
|
||||
*)
|
||||
|
@@ -6,4 +6,4 @@ path_scripts="$path_root/scripts"
|
||||
path_thirdparty="$path_root/thirdparty"
|
||||
|
||||
if [ -d "$path_build" ]; then rm -rf "$path_build"; fi
|
||||
# if [ -d "$path_thirdparty" ]; then rm -rf "$path_thirdparty"; fi
|
||||
# if [ -d "$path_thirdparty" ]; then rm -rf "$path_thirdparty"; fi
|
||||
|
@@ -24,7 +24,7 @@ $flag_format_odin = '--format=sokol_odin'
|
||||
$flag_module = '--module'
|
||||
|
||||
push-location $path_backend_sokol
|
||||
& $sokol_shdc --input $shadersrc_blit_atlas --output $shaderout_blit_atlas --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin $flag_module='blit_atlas'
|
||||
& $sokol_shdc --input $shadersrc_render_glyph --output $shaderout_render_glyph --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin $flag_module='render_glyph'
|
||||
& $sokol_shdc --input $shadersrc_draw_text --output $shaderout_draw_text --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin $flag_module='draw_text'
|
||||
& $sokol_shdc --input $shadersrc_blit_atlas --output $shaderout_blit_atlas --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin
|
||||
& $sokol_shdc --input $shadersrc_render_glyph --output $shaderout_render_glyph --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin
|
||||
& $sokol_shdc --input $shadersrc_draw_text --output $shaderout_draw_text --slang 'glsl410:glsl300es:hlsl4:metal_macos:wgsl' $flag_format_odin
|
||||
pop-location
|
||||
|
@@ -45,17 +45,17 @@ pushd "$path_backend_sokol" > /dev/null
|
||||
|
||||
"$sokol_shdc" "$flag_input" "$shadersrc_blit_atlas" \
|
||||
"$flag_output" "$shaderout_blit_atlas" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:metal_macos:wgsl" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:hlsl4:metal_macos:wgsl" \
|
||||
"$flag_format_odin" "$flag_module=blit_atlas"
|
||||
|
||||
"$sokol_shdc" "$flag_input" "$shadersrc_render_glyph" \
|
||||
"$flag_output" "$shaderout_render_glyph" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:metal_macos:wgsl" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:hlsl4:metal_macos:wgsl" \
|
||||
"$flag_format_odin" "$flag_module=render_glyph"
|
||||
|
||||
"$sokol_shdc" "$flag_input" "$shadersrc_draw_text" \
|
||||
"$flag_output" "$shaderout_draw_text" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:metal_macos:wgsl" \
|
||||
"$flag_target_lang" "glsl410:glsl300es:hlsl4:metal_macos:wgsl" \
|
||||
"$flag_format_odin" "$flag_module=draw_text"
|
||||
|
||||
echo "Built sokol shaders"
|
||||
|
@@ -65,6 +65,10 @@ function Update-GitRepo
|
||||
write-host
|
||||
return
|
||||
}
|
||||
|
||||
if ( -not(test-path -Path (join-path $path '.git'))) {
|
||||
return # Assume the user doesn't want to use git grab packages automatically.
|
||||
}
|
||||
|
||||
git -C $path fetch
|
||||
$latest_commit_hash = git -C $path rev-parse '@{u}'
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
clone_gitrepo() {
|
||||
clone_git_repo() {
|
||||
local path="$1"
|
||||
local url="$2"
|
||||
|
||||
@@ -77,6 +77,10 @@ update_git_repo() {
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -d "$path/.git" ]; then
|
||||
return # Assume the user doesn't want to use git grab packages automatically.
|
||||
fi
|
||||
|
||||
git -C "$path" fetch
|
||||
local latest_commit_hash=$(git -C "$path" rev-parse '@{u}')
|
||||
local last_built_hash=""
|
||||
|
@@ -63,3 +63,4 @@ flag_vet_using_stmt='-vet-using-stmt'
|
||||
|
||||
# Assuming to be in default path, change if otherwise
|
||||
odin_compiler='odin'
|
||||
# odin_compiler='/mnt/c/projects/SectrPrototype/toolchain/Odin/odin'
|
||||
|
10
thirdparty/harfbuzz/README.md
vendored
Normal file
10
thirdparty/harfbuzz/README.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# harfbuzz-odin
|
||||
|
||||
Harbuzz bindings for odin.
|
||||
|
||||
Its not the full amount, just enough to utilize its base shaping functionality.
|
||||
|
||||
## scripts/build.ps1
|
||||
|
||||
I only have support for building on Windows & Linux. However, Mac and Linux technically can just reference the library from their respective package managers.
|
||||
Will pull the latest source from the harfbuzz repository and build requisite libraries. Adjust the code as needed, by default a custom unity build is done (see `Build-RepoWithoutMeson`).
|
345
thirdparty/harfbuzz/harfbuzz.odin
vendored
Normal file
345
thirdparty/harfbuzz/harfbuzz.odin
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
NOTE(Ed): These bindings are currently partial for usage in a VE Font Cache port.
|
||||
*/
|
||||
package harfbuzz
|
||||
|
||||
import "core:c"
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
// @(extra_linker_flags="/NODEFAULTLIB:msvcrt")
|
||||
// foreign import harfbuzz "./lib/win64/libharfbuzz-0.dll"
|
||||
foreign import harfbuzz "./lib/win64/harfbuzz.lib"
|
||||
// foreign import harfbuzz "./lib/win64/libharfbuzz.a"
|
||||
}
|
||||
else when ODIN_OS == .Linux {
|
||||
// foreign import harfbuzz "./lib/linux64/libharfbuzz.so"
|
||||
foreign import harfbuzz "system:harfbuzz"
|
||||
}
|
||||
else when ODIN_OS == .Darwin {
|
||||
// foreign import harfbuzz { "./lib/osx/libharfbuzz.so" }
|
||||
foreign import harfbuzz "system:harfbuzz"
|
||||
}
|
||||
|
||||
Buffer :: distinct rawptr // hb_buffer_t*
|
||||
Blob :: distinct rawptr // hb_blob_t*
|
||||
Codepoint :: distinct c.uint32_t // hb_codepoint_t
|
||||
Face :: distinct rawptr // hb_face_t*
|
||||
Font :: distinct rawptr // hb_font_t*
|
||||
Language :: distinct rawptr // hb_language_t*
|
||||
Mask :: distinct c.uint32_t // hb_mask_t
|
||||
Position :: distinct c.uint32_t // hb_position_t
|
||||
Tag :: distinct c.uint32_t // hb_tag_t
|
||||
Unicode_Funcs :: distinct rawptr // hb_unicode_funcs_t*
|
||||
|
||||
hb_var_int_t :: struct #raw_union {
|
||||
u32 : c.uint32_t,
|
||||
i32 : c.int32_t,
|
||||
u16 : [2]c.uint16_t,
|
||||
i16 : [2]c.int16_t,
|
||||
u8 : [4]c.uint8_t,
|
||||
i8 : [4]c.int8_t,
|
||||
}
|
||||
|
||||
Feature :: struct {
|
||||
tag : Tag,
|
||||
value : c.uint32_t,
|
||||
start : c.uint,
|
||||
end : c.uint,
|
||||
}
|
||||
|
||||
Glyph_Info :: struct {
|
||||
codepoint : Codepoint,
|
||||
/*< private >*/
|
||||
mask : Mask,
|
||||
/*< public >*/
|
||||
cluster : c.uint32_t,
|
||||
|
||||
/*< private >*/
|
||||
var1 : hb_var_int_t,
|
||||
var2 : hb_var_int_t,
|
||||
}
|
||||
|
||||
Glyph_Position :: struct {
|
||||
x_advance : Position,
|
||||
y_advance : Position,
|
||||
x_offset : Position,
|
||||
y_offset : Position,
|
||||
|
||||
/*< private >*/
|
||||
var : hb_var_int_t,
|
||||
}
|
||||
|
||||
Segment_Properties :: struct {
|
||||
direction : Direction,
|
||||
script : Script,
|
||||
language : Language,
|
||||
reserved1 : rawptr,
|
||||
reserved2 : rawptr,
|
||||
}
|
||||
|
||||
Buffer_Content_Type :: enum c.uint {
|
||||
INVALID = 0,
|
||||
UNICODE,
|
||||
GLYPHS
|
||||
}
|
||||
|
||||
Direction :: enum c.uint {
|
||||
INVALID = 0,
|
||||
LGR = 4,
|
||||
RTL,
|
||||
TTB,
|
||||
BTT,
|
||||
}
|
||||
|
||||
Script :: enum u32 {
|
||||
// ID = ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF))),
|
||||
|
||||
// 1.1
|
||||
COMMON = ( u32('Z') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('y') & 0xFF ) << 8 | ( u32('y') & 0xFF ),
|
||||
INHERITED = ( u32('Z') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
|
||||
// 5.0
|
||||
UNKNOWN = ( u32('Z') & 0xFF ) << 24 | ( u32('z') & 0xFF ) << 16 | ( u32('z') & 0xFF ) << 8 | ( u32('z') & 0xFF ),
|
||||
|
||||
// 1.1
|
||||
ARABIC = ( u32('A') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
ARMENIAN = ( u32('A') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('n') & 0xFF ),
|
||||
BENGALI = ( u32('B') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
CYRILLIC = ( u32('C') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('l') & 0xFF ),
|
||||
DEVANAGARI = ( u32('D') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('v') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
GEORGIAN = ( u32('G') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
GREEK = ( u32('G') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('e') & 0xFF ) << 8 | ( u32('k') & 0xFF ),
|
||||
GUJARATI = ( u32('G') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('j') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
GURMUKHI = ( u32('G') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('u') & 0xFF ),
|
||||
HANGUL = ( u32('H') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
HAN = ( u32('H') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
HEBREW = ( u32('H') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('b') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
HIRAGANA = ( u32('H') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
KANNADA = ( u32('K') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('d') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
KATAKANA = ( u32('K') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
LAO = ( u32('L') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
LATIN = ( u32('L') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('n') & 0xFF ),
|
||||
MALAYALAN = ( u32('M') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('y') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
ORIYA = ( u32('O') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('y') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
TAMIL = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('l') & 0xFF ),
|
||||
TELUGU = ( u32('T') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('u') & 0xFF ),
|
||||
THAI = ( u32('T') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
|
||||
// 2.0
|
||||
TIBETAN = ( u32('T') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('b') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
|
||||
// 3.0
|
||||
BOPOMOFO = ( u32('B') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('p') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
BRAILLE = ( u32('B') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
CANADIAN_SYLLABICS = ( u32('C') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('s') & 0xFF ),
|
||||
CHEROKEE = ( u32('C') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('e') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
ETHIOPIC = ( u32('E') & 0xFF ) << 24 | ( u32('t') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
KHMER = ( u32('K') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
MONGOLIAN = ( u32('M') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
MYANMAR = ( u32('M') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
OGHAM = ( u32('O') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('n') & 0xFF ),
|
||||
RUNIC = ( u32('R') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
SINHALA = ( u32('S') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
SYRIAC = ( u32('S') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('c') & 0xFF ),
|
||||
THAANA = ( u32('T') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
YI = ( u32('Y') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('i') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
|
||||
// 3.1
|
||||
DESERET = ( u32('D') & 0xFF ) << 24 | ( u32('s') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
GOTHIC = ( u32('G') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
OLD_ITALIC = ( u32('I') & 0xFF ) << 24 | ( u32('t') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('l') & 0xFF ),
|
||||
|
||||
// 3.2
|
||||
BUHID = ( u32('B') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
HANUNOO = ( u32('H') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
TAGALOG = ( u32('T') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
TAGBANWA = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
|
||||
// 4.0
|
||||
CYPRIOT = ( u32('C') & 0xFF ) << 24 | ( u32('p') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
LIMBU = ( u32('L') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
LINEAR_B = ( u32('L') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('i') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
OSMANYA = ( u32('O') & 0xFF ) << 24 | ( u32('m') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
SHAVIAN = ( u32('S') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('w') & 0xFF ),
|
||||
TAI_LE = ( u32('T') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('e') & 0xFF ),
|
||||
UGARITIC = ( u32('U') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
|
||||
// 4.1
|
||||
BUGINESE = ( u32('B') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
COPTIC = ( u32('C') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('p') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
GLAGOLITIC = ( u32('G') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
KHAROSHTHI = ( u32('K') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
NEW_TAI_LUE = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('u') & 0xFF ),
|
||||
OLD_PERSIAN = ( u32('X') & 0xFF ) << 24 | ( u32('p') & 0xFF ) << 16 | ( u32('e') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
SYLOTI_NAGRI = ( u32('S') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
TIFINAGH = ( u32('T') & 0xFF ) << 24 | ( u32('f') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
|
||||
// 5.0
|
||||
BALINESE = ( u32('B') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
CUNEIFORM = ( u32('X') & 0xFF ) << 24 | ( u32('s') & 0xFF ) << 16 | ( u32('u') & 0xFF ) << 8 | ( u32('x') & 0xFF ),
|
||||
NKO = ( u32('N') & 0xFF ) << 24 | ( u32('k') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
PHAGS_PA = ( u32('P') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
PHOENICIAN = ( u32('P') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('x') & 0xFF ),
|
||||
|
||||
// 5.1
|
||||
CARIAN = ( u32('C') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
CHAM = ( u32('C') & 0xFF ) << 24 | ( u32('j') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
KAYAH_LI = ( u32('K') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
LEPCHA = ( u32('L') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('p') & 0xFF ) << 8 | ( u32('c') & 0xFF ),
|
||||
LYCIAN = ( u32('L') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('c') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
LYDIAN = ( u32('L') & 0xFF ) << 24 | ( u32('y') & 0xFF ) << 16 | ( u32('d') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
OL_CHIKI = ( u32('O') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('c') & 0xFF ) << 8 | ( u32('k') & 0xFF ),
|
||||
REJANG = ( u32('R') & 0xFF ) << 24 | ( u32('n') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
SAURASHTRA = ( u32('S') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('u') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
SUNDANESE = ( u32('S') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
VAI = ( u32('V') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('i') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
|
||||
// 5.2
|
||||
AVESTAN = ( u32('A') & 0xFF ) << 24 | ( u32('v') & 0xFF ) << 16 | ( u32('s') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
BAMUM = ( u32('B') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('u') & 0xFF ),
|
||||
EGYPTIAN_HIEROGLYPHS = ( u32('E') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('y') & 0xFF ) << 8 | ( u32('p') & 0xFF ),
|
||||
IMPERIAL_ARAMAIC = ( u32('A') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
INSCRIPTIONAL_PAHLAVI = ( u32('P') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
INSCRIPTIONAL_PARTHAIAN = ( u32('P') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
JAVANESE = ( u32('J') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('v') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
KAITHI = ( u32('K') & 0xFF ) << 24 | ( u32('t') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
LISU = ( u32('L') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('s') & 0xFF ) << 8 | ( u32('u') & 0xFF ),
|
||||
MEETEI_MAYEK = ( u32('M') & 0xFF ) << 24 | ( u32('t') & 0xFF ) << 16 | ( u32('e') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
OLD_SOUTH_ARABIAN = ( u32('S') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
OLD_TURKIC = ( u32('O') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('k') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
SAMARITAN = ( u32('S') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('m') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
TAI_THAM = ( u32('L') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
TAI_VIET = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('v') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
|
||||
// 6.0
|
||||
BATAK = ( u32('B') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('k') & 0xFF ),
|
||||
BRAHMI = ( u32('B') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
MANDAIC = ( u32('M') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
|
||||
// 6.1
|
||||
CHAKMA = ( u32('C') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('k') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
MEROITIC_CURSIVE = ( u32('M') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('c') & 0xFF ),
|
||||
MEROITIC_HIEROGLYPHS = ( u32('M') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
MIAO = ( u32('P') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
SHARADA = ( u32('S') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
SORA_SOMPENG = ( u32('S') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
TAKRI = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('k') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
|
||||
// 0.9.30
|
||||
// 7.0
|
||||
BASSA_VAH = ( u32('B') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('s') & 0xFF ) << 8 | ( u32('s') & 0xFF ),
|
||||
CAUCASIAN_ALBANIAN = ( u32('A') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
DUPLOYAN = ( u32('D') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('p') & 0xFF ) << 8 | ( u32('l') & 0xFF ),
|
||||
ELBASAN = ( u32('E') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('b') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
GRANTHA = ( u32('G') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('n') & 0xFF ),
|
||||
KHOJKI = ( u32('K') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('j') & 0xFF ),
|
||||
KHUDAWADI = ( u32('S') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
LINEAR_A = ( u32('L') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
MAHAJANI = ( u32('M') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('j') & 0xFF ),
|
||||
MANICHAEAN = ( u32('M') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
MENDE_KIKAKUI = ( u32('M') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
MODI = ( u32('M') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('d') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
MRO = ( u32('M') & 0xFF ) << 24 | ( u32('r') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
NABATAEAN = ( u32('N') & 0xFF ) << 24 | ( u32('b') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
OLD_NORTH_ARABIAN = ( u32('N') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('b') & 0xFF ),
|
||||
OLD_PERMIC = ( u32('P') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
PAHAWH_HMONG = ( u32('H') & 0xFF ) << 24 | ( u32('m') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
PALMYRENE = ( u32('P') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
PAU_CIN_HAU = ( u32('P') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('u') & 0xFF ) << 8 | ( u32('c') & 0xFF ),
|
||||
PSALTER_PAHLAVI = ( u32('P') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('p') & 0xFF ),
|
||||
SIDDHAM = ( u32('S') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('d') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
TIRHUNTA = ( u32('T') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('h') & 0xFF ),
|
||||
WARANG_CITI = ( u32('W') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
|
||||
// 8.0
|
||||
AHOM = ( u32('A') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('o') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
ANATOLIAN_HIEROGLYPHS = ( u32('H') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('u') & 0xFF ) << 8 | ( u32('w') & 0xFF ),
|
||||
HATRAN = ( u32('H') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
MULTANI = ( u32('M') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('t') & 0xFF ),
|
||||
OLD_HUNGARIAN = ( u32('H') & 0xFF ) << 24 | ( u32('u') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
SIGNWRITING = ( u32('S') & 0xFF ) << 24 | ( u32('g') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('w') & 0xFF ),
|
||||
|
||||
// 1.3.0
|
||||
// 9.0
|
||||
ADLAM = ( u32('A') & 0xFF ) << 24 | ( u32('d') & 0xFF ) << 16 | ( u32('l') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
BHAIKSUKI = ( u32('B') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('k') & 0xFF ) << 8 | ( u32('s') & 0xFF ),
|
||||
MARCHEN = ( u32('M') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('c') & 0xFF ),
|
||||
OSAGE = ( u32('O') & 0xFF ) << 24 | ( u32('s') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('e') & 0xFF ),
|
||||
TANGUT = ( u32('T') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
NEWA = ( u32('N') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('w') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
|
||||
// 1.6.0
|
||||
// 10.0
|
||||
MASARAM_GONDI = ( u32('D') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
NUSHU = ( u32('D') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
SOYOMBO = ( u32('D') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
ZANABAZAR_SQUARE = ( u32('D') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
|
||||
// 1.8.0
|
||||
// 11.0
|
||||
DOGRA = ( u32('D') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('r') & 0xFF ),
|
||||
GUNJALA_GONDI = ( u32('G') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
HANIFI_ROHINGYA = ( u32('R') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('g') & 0xFF ),
|
||||
MAKASAR = ( u32('M') & 0xFF ) << 24 | ( u32('k') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('a') & 0xFF ),
|
||||
MEDEFAIDRIN = ( u32('M') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('d') & 0xFF ) << 8 | ( u32('f') & 0xFF ),
|
||||
OLD_SOGDIAN = ( u32('S') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
SOGDIAN = ( u32('S') & 0xFF ) << 24 | ( u32('o') & 0xFF ) << 16 | ( u32('g') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
|
||||
// 2.4.0
|
||||
// 12.0
|
||||
ELYMAIC = ( u32('E') & 0xFF ) << 24 | ( u32('l') & 0xFF ) << 16 | ( u32('y') & 0xFF ) << 8 | ( u32('m') & 0xFF ),
|
||||
NANDINAGARI = ( u32('N') & 0xFF ) << 24 | ( u32('a') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('d') & 0xFF ),
|
||||
NYIAKENG_PUACHUE_HMONG = ( u32('H') & 0xFF ) << 24 | ( u32('m') & 0xFF ) << 16 | ( u32('n') & 0xFF ) << 8 | ( u32('p') & 0xFF ),
|
||||
WANCHO = ( u32('W') & 0xFF ) << 24 | ( u32('c') & 0xFF ) << 16 | ( u32('h') & 0xFF ) << 8 | ( u32('o') & 0xFF ),
|
||||
|
||||
// 2.6.7
|
||||
// 13.0
|
||||
CHRASMIAN = ( u32('C') & 0xFF ) << 24 | ( u32('h') & 0xFF ) << 16 | ( u32('r') & 0xFF ) << 8 | ( u32('s') & 0xFF ),
|
||||
DIVES_AKURU = ( u32('D') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('a') & 0xFF ) << 8 | ( u32('k') & 0xFF ),
|
||||
KHITAN_SMALL_SCRIPT = ( u32('K') & 0xFF ) << 24 | ( u32('i') & 0xFF ) << 16 | ( u32('t') & 0xFF ) << 8 | ( u32('s') & 0xFF ),
|
||||
YEZIDI = ( u32('Y') & 0xFF ) << 24 | ( u32('e') & 0xFF ) << 16 | ( u32('z') & 0xFF ) << 8 | ( u32('i') & 0xFF ),
|
||||
|
||||
INVALID= 0,
|
||||
}
|
||||
|
||||
Memory_Mode :: enum c.int {
|
||||
DUPLICATE,
|
||||
READONLY,
|
||||
WRITABLE,
|
||||
READONLY_MAY_MAKE_WRITABLE,
|
||||
}
|
||||
|
||||
Destroy_Func :: proc "c" ( user_data : rawptr )
|
||||
|
||||
@(default_calling_convention="c", link_prefix="hb_")
|
||||
foreign harfbuzz
|
||||
{
|
||||
blob_create :: proc( data : [^]u8, length : c.uint, memory_mode : Memory_Mode, user_data : rawptr, destroy : Destroy_Func ) -> Blob ---
|
||||
blob_destroy :: proc( blob : Blob ) ---
|
||||
|
||||
buffer_create :: proc() -> Buffer ---
|
||||
buffer_destroy :: proc( buffer : Buffer ) ---
|
||||
buffer_add :: proc( buffer : Buffer, codepoint : Codepoint, cluster : c.uint ) ---
|
||||
buffer_clear_contents :: proc( buffer : Buffer ) ---
|
||||
buffer_get_glyph_infos :: proc( buffer : Buffer, length : ^c.uint ) -> [^]Glyph_Info ---
|
||||
buffer_get_glyph_positions :: proc( buffer : Buffer, length : ^c.uint ) -> [^]Glyph_Position ---
|
||||
buffer_set_direction :: proc( buffer : Buffer, direction : Direction ) ---
|
||||
buffer_set_language :: proc( buffer : Buffer, language : Language ) ---
|
||||
buffer_set_script :: proc( buffer : Buffer, script : Script ) ---
|
||||
buffer_set_content_type :: proc( buffer : Buffer, content_type : Buffer_Content_Type ) ---
|
||||
|
||||
face_create :: proc( blob : Blob, index : c.uint ) -> Face ---
|
||||
face_destroy :: proc( face : Face ) ---
|
||||
|
||||
font_create :: proc( face : Face ) -> Font ---
|
||||
font_destroy :: proc( font : Font ) ---
|
||||
|
||||
language_get_default :: proc() -> Language ---
|
||||
|
||||
script_get_horizontal_direction :: proc( script : Script ) -> Direction ---
|
||||
|
||||
shape :: proc( font : Font, buffer : Buffer, features : [^]Feature, num_features : c.uint ) ---
|
||||
|
||||
unicode_funcs_get_default :: proc() -> Unicode_Funcs ---
|
||||
unicode_script :: proc( ufuncs : Unicode_Funcs, unicode : Codepoint ) -> Script ---
|
||||
}
|
BIN
thirdparty/harfbuzz/lib/linux64/libharfbuzz.so
vendored
Normal file
BIN
thirdparty/harfbuzz/lib/linux64/libharfbuzz.so
vendored
Normal file
Binary file not shown.
BIN
thirdparty/harfbuzz/lib/win64/harfbuzz.dll
vendored
Normal file
BIN
thirdparty/harfbuzz/lib/win64/harfbuzz.dll
vendored
Normal file
Binary file not shown.
BIN
thirdparty/harfbuzz/lib/win64/harfbuzz.lib
vendored
Normal file
BIN
thirdparty/harfbuzz/lib/win64/harfbuzz.lib
vendored
Normal file
Binary file not shown.
305
thirdparty/harfbuzz/scripts/build.ps1
vendored
Normal file
305
thirdparty/harfbuzz/scripts/build.ps1
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
$misc = join-path $PSScriptRoot 'helpers/misc.ps1'
|
||||
. $misc
|
||||
|
||||
$path_root = git rev-parse --show-toplevel
|
||||
$path_lib = join-path $path_root 'lib'
|
||||
$path_win64 = join-path $path_lib 'win64'
|
||||
|
||||
$url_harfbuzz = 'https://github.com/harfbuzz/harfbuzz.git'
|
||||
$path_harfbuzz = join-path $path_root 'harfbuzz'
|
||||
|
||||
function build-repo {
|
||||
verify-path $script:path_lib
|
||||
verify-path $path_win64
|
||||
|
||||
clone-gitrepo $path_harfbuzz $url_harfbuzz
|
||||
|
||||
push-location $path_harfbuzz
|
||||
|
||||
$library_type = "shared"
|
||||
$build_type = "release"
|
||||
|
||||
# Meson configure and build
|
||||
$mesonArgs = @(
|
||||
"build",
|
||||
"--default-library=$library_type",
|
||||
"--buildtype=$build_type",
|
||||
"--wrap-mode=forcefallback",
|
||||
"-Dglib=disabled",
|
||||
"-Dgobject=disabled",
|
||||
"-Dcairo=disabled",
|
||||
"-Dicu=disabled",
|
||||
"-Dgraphite=disabled",
|
||||
"-Dfreetype=disabled",
|
||||
"-Ddirectwrite=disabled",
|
||||
"-Dcoretext=disabled"
|
||||
)
|
||||
& meson $mesonArgs
|
||||
& meson compile -C build
|
||||
|
||||
pop-location
|
||||
|
||||
$path_build = join-path $path_harfbuzz 'build'
|
||||
$path_src = join-path $path_build 'src'
|
||||
$path_dll = join-path $path_src 'harfbuzz.dll'
|
||||
$path_lib = join-path $path_src 'harfbuzz.lib'
|
||||
$path_lib_static = join-path $path_src 'libharfbuzz.a'
|
||||
$path_pdb = join-path $path_src 'harfbuzz.pdb'
|
||||
|
||||
# Copy files based on build type and library type
|
||||
if ($build_type -eq "debug") {
|
||||
copy-item -Path $path_pdb -Destination $path_win64 -Force
|
||||
}
|
||||
|
||||
if ($library_type -eq "static") {
|
||||
copy-item -Path $path_lib_static -Destination (join-path $path_win64 'harfbuzz.lib') -Force
|
||||
}
|
||||
else {
|
||||
copy-item -Path $path_lib -Destination $path_win64 -Force
|
||||
copy-item -Path $path_dll -Destination $path_win64 -Force
|
||||
}
|
||||
|
||||
write-host "Build completed and files copied to $path_win64"
|
||||
}
|
||||
# build-repo
|
||||
|
||||
function Build-RepoWithoutMeson {
|
||||
$devshell = join-path $PSScriptRoot 'helpers/devshell.ps1'
|
||||
& $devshell -arch amd64
|
||||
|
||||
verify-path $script:path_lib
|
||||
verify-path $path_win64
|
||||
|
||||
clone-gitrepo $path_harfbuzz $url_harfbuzz
|
||||
|
||||
$path_harfbuzz_build = join-path $path_harfbuzz 'build'
|
||||
verify-path $path_harfbuzz_build
|
||||
|
||||
$library_type = "shared"
|
||||
$build_type = "release"
|
||||
|
||||
push-location $path_harfbuzz
|
||||
|
||||
$compiler_args = @(
|
||||
"/nologo",
|
||||
"/W3",
|
||||
"/D_CRT_SECURE_NO_WARNINGS",
|
||||
"/DHAVE_FALLBACK=1",
|
||||
"/DHAVE_OT=1",
|
||||
"/DHAVE_SUBSET=1",
|
||||
"/DHB_USE_INTERNAL_PARSER",
|
||||
"/DHB_NO_COLOR",
|
||||
"/DHB_NO_DRAW",
|
||||
"/DHB_NO_PARSE",
|
||||
"/DHB_NO_MT",
|
||||
"/DHB_NO_GRAPHITE2",
|
||||
"/DHB_NO_ICU",
|
||||
"/DHB_NO_DIRECTWRITE",
|
||||
"/I$path_harfbuzz\src",
|
||||
"/I$path_harfbuzz"
|
||||
)
|
||||
|
||||
if ( $library_type -eq "shared" ) {
|
||||
$compiler_args += "/DHAVE_DECLSPEC"
|
||||
$compiler_args += "/DHARFBUZZ_EXPORTS"
|
||||
}
|
||||
|
||||
if ($build_type -eq "debug") {
|
||||
$compiler_args += "/MDd", "/Od", "/Zi"
|
||||
} else {
|
||||
$compiler_args += "/MD", "/O2"
|
||||
}
|
||||
|
||||
$compiler_args = $compiler_args -join " "
|
||||
|
||||
$config_h_content = @"
|
||||
#define HB_VERSION_MAJOR 9
|
||||
#define HB_VERSION_MINOR 0
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_STRING "9.0.0"
|
||||
#define HAVE_ROUND 1
|
||||
#define HB_NO_BITMAP 1
|
||||
#define HB_NO_CFF 1
|
||||
#define HB_NO_OT_FONT_CFF 1
|
||||
#define HB_NO_SUBSET_CFF 1
|
||||
#define HB_HAVE_SUBSET 0
|
||||
#define HB_HAVE_OT 0
|
||||
#define HB_USER_DATA_KEY_DEFINE1(_name) extern HB_EXTERN hb_user_data_key_t _name
|
||||
"@
|
||||
set-content -Path (join-path $path_harfbuzz "config.h") -Value $config_h_content
|
||||
|
||||
$unity_content = @"
|
||||
#define HB_EXTERN __declspec(dllexport)
|
||||
|
||||
// base
|
||||
#include "config.h"
|
||||
#include "hb-aat-layout.cc"
|
||||
#include "hb-aat-map.cc"
|
||||
#include "hb-blob.cc"
|
||||
#include "hb-buffer-serialize.cc"
|
||||
#include "hb-buffer-verify.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
|
||||
//#include "hb-draw.cc"
|
||||
//#include "hb-paint.cc"
|
||||
//#include "hb-paint-extents.cc"
|
||||
|
||||
#include "hb-face.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
#include "hb-map.cc"
|
||||
#include "hb-number.cc"
|
||||
#include "hb-ot-cff1-table.cc"
|
||||
#include "hb-ot-cff2-table.cc"
|
||||
#include "hb-ot-color.cc"
|
||||
#include "hb-ot-face.cc"
|
||||
#include "hb-ot-font.cc"
|
||||
|
||||
#include "hb-outline.cc"
|
||||
#include "OT/Var/VARC/VARC.cc"
|
||||
|
||||
#include "hb-ot-layout.cc"
|
||||
#include "hb-ot-map.cc"
|
||||
#include "hb-ot-math.cc"
|
||||
#include "hb-ot-meta.cc"
|
||||
#include "hb-ot-metrics.cc"
|
||||
#include "hb-ot-name.cc"
|
||||
|
||||
#include "hb-ot-shaper-arabic.cc"
|
||||
#include "hb-ot-shaper-default.cc"
|
||||
#include "hb-ot-shaper-hangul.cc"
|
||||
#include "hb-ot-shaper-hebrew.cc"
|
||||
#include "hb-ot-shaper-indic-table.cc"
|
||||
#include "hb-ot-shaper-indic.cc"
|
||||
#include "hb-ot-shaper-khmer.cc"
|
||||
#include "hb-ot-shaper-myanmar.cc"
|
||||
#include "hb-ot-shaper-syllabic.cc"
|
||||
#include "hb-ot-shaper-thai.cc"
|
||||
#include "hb-ot-shaper-use.cc"
|
||||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
|
||||
#include "hb-ot-shape-fallback.cc"
|
||||
#include "hb-ot-shape-normalize.cc"
|
||||
#include "hb-ot-shape.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
|
||||
#include "hb-set.cc"
|
||||
#include "hb-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
#include "hb-shaper.cc"
|
||||
#include "hb-static.cc"
|
||||
#include "hb-style.cc"
|
||||
#include "hb-ucd.cc"
|
||||
#include "hb-unicode.cc"
|
||||
|
||||
// libharfbuzz-subset
|
||||
//#include "hb-subset-input.cc"
|
||||
//#include "hb-subset-cff-common.cc"
|
||||
//#include "hb-subset-cff1.cc"
|
||||
//#include "hb-subset-cff2.cc"
|
||||
//#include "hb-subset-instancer-iup.cc"
|
||||
//#include "hb-subset-instancer-solver.cc"
|
||||
//#include "hb-subset-plan.cc"
|
||||
//#include "hb-subset-repacker.cc"
|
||||
|
||||
//#include "graph/gsubgpos-context.cc"
|
||||
|
||||
//#include "hb-subset.cc"
|
||||
"@
|
||||
$unity_file = join-path $path_harfbuzz_build "harfbuzz_unity.cc"
|
||||
set-content -Path $unity_file -Value $unity_content
|
||||
|
||||
# Compile unity file
|
||||
$obj_file = "harfbuzz_unity.obj"
|
||||
$command = "cl.exe $compiler_args /c $unity_file /Fo$path_harfbuzz_build\$obj_file"
|
||||
|
||||
write-host "Compiling: $command"
|
||||
invoke-expression $command
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
write-error "Compilation failed for unity build"
|
||||
pop-location
|
||||
return
|
||||
}
|
||||
|
||||
push-location $path_harfbuzz_build
|
||||
|
||||
# Create library
|
||||
if ($library_type -eq "static")
|
||||
{
|
||||
$lib_command = "lib.exe /OUT:harfbuzz.lib $obj_file"
|
||||
|
||||
write-host "Creating static library: $lib_command"
|
||||
invoke-expression $lib_command
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Static library creation failed"
|
||||
pop-location
|
||||
pop-location
|
||||
return
|
||||
}
|
||||
$output_file = "harfbuzz.lib"
|
||||
}
|
||||
else
|
||||
{
|
||||
$linker_args = "/DLL", "/OUT:harfbuzz.dll"
|
||||
|
||||
if ($build_type -eq "debug") {
|
||||
$linker_args += "/DEBUG"
|
||||
}
|
||||
|
||||
$link_command = "link.exe $($linker_args -join ' ') $obj_file"
|
||||
|
||||
write-host "Creating shared library: $link_command"
|
||||
invoke-expression $link_command
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
write-error "Shared library creation failed"
|
||||
pop-location
|
||||
pop-location
|
||||
return
|
||||
}
|
||||
$output_file = "harfbuzz.dll"
|
||||
}
|
||||
|
||||
pop-location # path_harfbuzz_build
|
||||
pop-location # path_harfbuzz
|
||||
|
||||
# Copy files
|
||||
$path_output = join-path $path_harfbuzz_build $output_file
|
||||
|
||||
if (test-path $path_output) {
|
||||
copy-item -Path $path_output -Destination $path_win64 -Force
|
||||
if ($library_type -eq "shared") {
|
||||
$path_lib = join-path $path_harfbuzz_build "harfbuzz.lib"
|
||||
if (test-path $path_lib) {
|
||||
copy-item -Path $path_lib -Destination $path_win64 -Force
|
||||
}
|
||||
}
|
||||
} else {
|
||||
write-warning "Output file not found: $path_output"
|
||||
}
|
||||
|
||||
write-host "Build completed and files copied to $path_win64"
|
||||
}
|
||||
Build-RepoWithoutMeson
|
||||
|
||||
function grab-binaries {
|
||||
verify-path $script:path_lib
|
||||
verify-path $path_win64
|
||||
|
||||
$url_harfbuzz_8_5_0_win64 = 'https://github.com/harfbuzz/harfbuzz/releases/latest/download/harfbuzz-win64-8.5.0.zip'
|
||||
$path_harfbuzz_win64_zip = join-path $path_win64 'harfbuzz-win64-8.5.0.zip'
|
||||
$path_harfbuzz_win64 = join-path $path_win64 'harfbuzz-win64'
|
||||
|
||||
grab-zip $url_harfbuzz_8_5_0_win64 $path_harfbuzz_win64_zip $path_win64
|
||||
get-childitem -path $path_harfbuzz_win64 | move-item -destination $path_win64 -force
|
||||
|
||||
# Clean up the ZIP file and the now empty harfbuzz-win64 directory
|
||||
remove-item $path_harfbuzz_win64_zip -force
|
||||
remove-item $path_harfbuzz_win64 -recurse -force
|
||||
}
|
||||
# grab-binaries
|
284
thirdparty/harfbuzz/scripts/build.sh
vendored
Normal file
284
thirdparty/harfbuzz/scripts/build.sh
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Source the misc.sh script
|
||||
misc_script="$(dirname "$0")/helpers/misc.sh"
|
||||
chmod +x "$misc_script"
|
||||
source "$misc_script"
|
||||
|
||||
path_root=$(git rev-parse --show-toplevel)
|
||||
path_lib="$path_root/lib"
|
||||
path_osx="$path_lib/osx"
|
||||
path_linux64="$path_lib/linux64"
|
||||
|
||||
OS=$(uname -s)
|
||||
|
||||
# Set the appropriate output directory and file extension
|
||||
case "$OS" in
|
||||
Darwin*)
|
||||
path_output="$path_osx"
|
||||
shared_lib_extension="dylib"
|
||||
;;
|
||||
Linux*)
|
||||
path_output="$path_linux64"
|
||||
shared_lib_extension="so"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported operating system: $OS"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
url_harfbuzz='https://github.com/harfbuzz/harfbuzz.git'
|
||||
path_harfbuzz="$path_root/harfbuzz"
|
||||
|
||||
build_repo() {
|
||||
verify_path "$path_lib"
|
||||
verify_path "$path_output"
|
||||
|
||||
# grab the actual repo
|
||||
clone_gitrepo "$path_harfbuzz" "$url_harfbuzz"
|
||||
|
||||
pushd "$path_harfbuzz" > /dev/null
|
||||
|
||||
library_type="shared"
|
||||
build_type="release"
|
||||
|
||||
# Check if meson is installed
|
||||
if ! command -v meson &> /dev/null; then
|
||||
echo "Meson is not installed. Please install it and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Meson configure and build
|
||||
meson_args=(
|
||||
"build"
|
||||
"--default-library=$library_type"
|
||||
"--buildtype=$build_type"
|
||||
"--wrap-mode=forcefallback"
|
||||
"-Dglib=disabled"
|
||||
"-Dgobject=disabled"
|
||||
"-Dcairo=disabled"
|
||||
"-Dicu=disabled"
|
||||
"-Dgraphite=disabled"
|
||||
"-Dfreetype=disabled"
|
||||
"-Ddirectwrite=disabled"
|
||||
"-Dcoretext=disabled"
|
||||
)
|
||||
meson "${meson_args[@]}"
|
||||
ninja -C build
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
path_build="$path_harfbuzz/build"
|
||||
path_src="$path_build/src"
|
||||
path_so="$path_src/libharfbuzz.so"
|
||||
path_a="$path_src/libharfbuzz.a"
|
||||
|
||||
# Copy files based on build type and library type
|
||||
if [ "$build_type" = "debug" ]; then
|
||||
# Debug symbols are typically embedded in the .so file on Linux
|
||||
# If there's a separate debug file, you would copy it here
|
||||
:
|
||||
fi
|
||||
|
||||
if [ "$library_type" = "static" ]; then
|
||||
cp "$path_a" "$path_linux64/libharfbuzz.a"
|
||||
else
|
||||
cp "$path_so" "$path_linux64/libharfbuzz.so"
|
||||
fi
|
||||
|
||||
echo "Build completed and files copied to $path_linux64"
|
||||
}
|
||||
|
||||
build_repo_without_meson() {
|
||||
# Detect the operating system
|
||||
OS=$(uname -s)
|
||||
|
||||
echo $url_harfbuzz
|
||||
echo $path_harfbuzz
|
||||
echo $path_lib
|
||||
echo $path_linux64
|
||||
verify_path "$path_lib"
|
||||
verify_path "$path_linux64"
|
||||
|
||||
path_harfbuzz_build="$path_harfbuzz/build"
|
||||
echo $path_harfbuzz_build
|
||||
|
||||
# grab the actual repo
|
||||
clone_gitrepo "$path_harfbuzz" "$url_harfbuzz"
|
||||
|
||||
verify_path "$path_harfbuzz_build"
|
||||
|
||||
library_type="shared"
|
||||
build_type="release"
|
||||
|
||||
pushd "$path_harfbuzz" > /dev/null
|
||||
|
||||
# Determine the latest C++ standard supported by the compiler
|
||||
latest_cpp_standard=$(clang++ -dM -E - < /dev/null | grep __cplusplus | awk '{print $3}')
|
||||
case $latest_cpp_standard in
|
||||
201703L) cpp_flag="-std=c++17" ;;
|
||||
202002L) cpp_flag="-std=c++20" ;;
|
||||
202302L) cpp_flag="-std=c++23" ;;
|
||||
*) cpp_flag="-std=c++14" ;; # Default to C++14 if unable to determine
|
||||
esac
|
||||
echo "Using C++ standard: $cpp_flag"
|
||||
|
||||
compiler_args=(
|
||||
"$cpp_flag"
|
||||
"-Wall"
|
||||
"-Wextra"
|
||||
"-D_REENTRANT"
|
||||
"-DHAVE_FALLBACK=1"
|
||||
"-DHAVE_OT=1"
|
||||
"-DHAVE_SUBSET=1"
|
||||
"-DHB_USE_INTERNAL_PARSER"
|
||||
"-DHB_NO_COLOR"
|
||||
"-DHB_NO_DRAW"
|
||||
"-DHB_NO_PARSE"
|
||||
"-DHB_NO_MT"
|
||||
"-DHB_NO_GRAPHITE2"
|
||||
"-DHB_NO_ICU"
|
||||
"-DHB_NO_DIRECTWRITE"
|
||||
"-I$path_harfbuzz/src"
|
||||
"-I$path_harfbuzz"
|
||||
)
|
||||
|
||||
if [ "$library_type" = "shared" ]; then
|
||||
compiler_args+=("-fPIC")
|
||||
compiler_args+=("-DHAVE_DECLSPEC")
|
||||
compiler_args+=("-DHARFBUZZ_EXPORTS")
|
||||
fi
|
||||
|
||||
if [ "$build_type" = "debug" ]; then
|
||||
compiler_args+=("-g" "-O0")
|
||||
else
|
||||
compiler_args+=("-O2")
|
||||
fi
|
||||
|
||||
compiler_args_str="${compiler_args[*]}"
|
||||
|
||||
# Create config.h
|
||||
cat > "$path_harfbuzz/config.h" << EOL
|
||||
#define HB_VERSION_MAJOR 9
|
||||
#define HB_VERSION_MINOR 0
|
||||
#define HB_VERSION_MICRO 0
|
||||
#define HB_VERSION_STRING "9.0.0"
|
||||
#define HAVE_ROUND 1
|
||||
#define HB_NO_BITMAP 1
|
||||
#define HB_NO_CFF 1
|
||||
#define HB_NO_OT_FONT_CFF 1
|
||||
#define HB_NO_SUBSET_CFF 1
|
||||
#define HB_HAVE_SUBSET 0
|
||||
#define HB_HAVE_OT 0
|
||||
#define HB_USER_DATA_KEY_DEFINE1(_name) extern HB_EXTERN hb_user_data_key_t _name
|
||||
EOL
|
||||
|
||||
# Create unity build file
|
||||
cat > "$path_harfbuzz_build/harfbuzz_unity.cc" << EOL
|
||||
#define HB_EXTERN __attribute__((visibility("default")))
|
||||
|
||||
// base
|
||||
#include "config.h"
|
||||
#include "hb-aat-layout.cc"
|
||||
#include "hb-aat-map.cc"
|
||||
#include "hb-blob.cc"
|
||||
#include "hb-buffer-serialize.cc"
|
||||
#include "hb-buffer-verify.cc"
|
||||
#include "hb-buffer.cc"
|
||||
#include "hb-common.cc"
|
||||
#include "hb-face.cc"
|
||||
#include "hb-face-builder.cc"
|
||||
#include "hb-fallback-shape.cc"
|
||||
#include "hb-font.cc"
|
||||
#include "hb-map.cc"
|
||||
#include "hb-number.cc"
|
||||
#include "hb-ot-cff1-table.cc"
|
||||
#include "hb-ot-cff2-table.cc"
|
||||
#include "hb-ot-color.cc"
|
||||
#include "hb-ot-face.cc"
|
||||
#include "hb-ot-font.cc"
|
||||
#include "hb-outline.cc"
|
||||
#include "OT/Var/VARC/VARC.cc"
|
||||
#include "hb-ot-layout.cc"
|
||||
#include "hb-ot-map.cc"
|
||||
#include "hb-ot-math.cc"
|
||||
#include "hb-ot-meta.cc"
|
||||
#include "hb-ot-metrics.cc"
|
||||
#include "hb-ot-name.cc"
|
||||
#include "hb-ot-shaper-arabic.cc"
|
||||
#include "hb-ot-shaper-default.cc"
|
||||
#include "hb-ot-shaper-hangul.cc"
|
||||
#include "hb-ot-shaper-hebrew.cc"
|
||||
#include "hb-ot-shaper-indic-table.cc"
|
||||
#include "hb-ot-shaper-indic.cc"
|
||||
#include "hb-ot-shaper-khmer.cc"
|
||||
#include "hb-ot-shaper-myanmar.cc"
|
||||
#include "hb-ot-shaper-syllabic.cc"
|
||||
#include "hb-ot-shaper-thai.cc"
|
||||
#include "hb-ot-shaper-use.cc"
|
||||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
#include "hb-ot-shape-fallback.cc"
|
||||
#include "hb-ot-shape-normalize.cc"
|
||||
#include "hb-ot-shape.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
#include "hb-set.cc"
|
||||
#include "hb-shape-plan.cc"
|
||||
#include "hb-shape.cc"
|
||||
#include "hb-shaper.cc"
|
||||
#include "hb-static.cc"
|
||||
#include "hb-style.cc"
|
||||
#include "hb-ucd.cc"
|
||||
#include "hb-unicode.cc"
|
||||
EOL
|
||||
|
||||
# Compile unity file
|
||||
pushd "$path_harfbuzz_build" > /dev/null
|
||||
g++ $compiler_args_str -c harfbuzz_unity.cc -o harfbuzz_unity.o
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Compilation failed for unity build"
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create library
|
||||
if [ "$library_type" = "static" ]; then
|
||||
ar rcs libharfbuzz.a harfbuzz_unity.o
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Static library creation failed"
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
return 1
|
||||
fi
|
||||
output_file="libharfbuzz.a"
|
||||
else
|
||||
g++ -shared -o libharfbuzz.so harfbuzz_unity.o
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Shared library creation failed"
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
return 1
|
||||
fi
|
||||
output_file="libharfbuzz.so"
|
||||
fi
|
||||
|
||||
popd > /dev/null # path_harfbuzz_build
|
||||
popd > /dev/null # path_harfbuzz
|
||||
|
||||
# Copy files
|
||||
cp "$path_harfbuzz_build/$output_file" "$path_linux64/"
|
||||
if [ "$library_type" = "shared" ]; then
|
||||
if [ -f "$path_harfbuzz_build/libharfbuzz.so" ]; then
|
||||
cp "$path_harfbuzz_build/libharfbuzz.so" "$path_linux64/"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Build completed and files copied to $path_linux64"
|
||||
}
|
||||
|
||||
# Uncomment the function you want to use
|
||||
# build_repo
|
||||
build_repo_without_meson
|
28
thirdparty/harfbuzz/scripts/helpers/devshell.ps1
vendored
Normal file
28
thirdparty/harfbuzz/scripts/helpers/devshell.ps1
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
if ($env:VCINSTALLDIR) {
|
||||
return
|
||||
}
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Use vswhere to find the latest Visual Studio installation
|
||||
$vswhere_out = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
|
||||
if ($null -eq $vswhere_out) {
|
||||
Write-Host "ERROR: Visual Studio installation not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Find Launch-VsDevShell.ps1 in the Visual Studio installation
|
||||
$vs_path = $vswhere_out
|
||||
$vs_devshell = Join-Path $vs_path "\Common7\Tools\Launch-VsDevShell.ps1"
|
||||
|
||||
if ( -not (Test-Path $vs_devshell) ) {
|
||||
Write-Host "ERROR: Launch-VsDevShell.ps1 not found in Visual Studio installation"
|
||||
Write-Host Tested path: $vs_devshell
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Launch the Visual Studio Developer Shell
|
||||
Push-Location
|
||||
write-host @args
|
||||
& $vs_devshell @args
|
||||
Pop-Location
|
72
thirdparty/harfbuzz/scripts/helpers/misc.ps1
vendored
Normal file
72
thirdparty/harfbuzz/scripts/helpers/misc.ps1
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
function Clone-Gitrepo { param( [string] $path, [string] $url )
|
||||
if (test-path $path) {
|
||||
# git -C $path pull
|
||||
}
|
||||
else {
|
||||
Write-Host "Cloning $url ..."
|
||||
git clone $url $path
|
||||
}
|
||||
}
|
||||
|
||||
function Grab-Zip { param( $url, $path_file, $path_dst )
|
||||
Invoke-WebRequest -Uri $url -OutFile $path_file
|
||||
Expand-Archive -Path $path_file -DestinationPath $path_dst -Force
|
||||
}
|
||||
|
||||
function Update-GitRepo
|
||||
{
|
||||
param( [string] $path, [string] $url, [string] $build_command )
|
||||
|
||||
if ( $build_command -eq $null ) {
|
||||
write-host "Attempted to call Update-GitRepo without build_command specified"
|
||||
return
|
||||
}
|
||||
|
||||
$repo_name = $url.Split('/')[-1].Replace('.git', '')
|
||||
|
||||
$last_built_commit = join-path $path_build "last_built_commit_$repo_name.txt"
|
||||
if ( -not(test-path -Path $path))
|
||||
{
|
||||
write-host "Cloining repo from $url to $path"
|
||||
git clone $url $path
|
||||
|
||||
write-host "Building $url"
|
||||
push-location $path
|
||||
& "$build_command"
|
||||
pop-location
|
||||
|
||||
git -C $path rev-parse HEAD | out-file $last_built_commit
|
||||
$script:binaries_dirty = $true
|
||||
write-host
|
||||
return
|
||||
}
|
||||
|
||||
git -C $path fetch
|
||||
$latest_commit_hash = git -C $path rev-parse '@{u}'
|
||||
$last_built_hash = if (Test-Path $last_built_commit) { Get-Content $last_built_commit } else { "" }
|
||||
|
||||
if ( $latest_commit_hash -eq $last_built_hash ) {
|
||||
write-host
|
||||
return
|
||||
}
|
||||
|
||||
write-host "Build out of date for: $path, updating"
|
||||
write-host 'Pulling...'
|
||||
git -C $path pull
|
||||
|
||||
write-host "Building $url"
|
||||
push-location $path
|
||||
& $build_command
|
||||
pop-location
|
||||
|
||||
$latest_commit_hash | out-file $last_built_commit
|
||||
$script:binaries_dirty = $true
|
||||
write-host
|
||||
}
|
||||
|
||||
function Verify-Path { param( $path )
|
||||
if (test-path $path) {return $true}
|
||||
|
||||
new-item -ItemType Directory -Path $path
|
||||
return $false
|
||||
}
|
111
thirdparty/harfbuzz/scripts/helpers/misc.sh
vendored
Normal file
111
thirdparty/harfbuzz/scripts/helpers/misc.sh
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
|
||||
clone_gitrepo() {
|
||||
local path="$1"
|
||||
local url="$2"
|
||||
|
||||
if [ -d "$path" ]; then
|
||||
# git -C "$path" pull
|
||||
:
|
||||
else
|
||||
echo "Cloning $url ..."
|
||||
git clone "$url" "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
get_ini_content() {
|
||||
local path_file="$1"
|
||||
declare -A ini
|
||||
|
||||
local current_section=""
|
||||
while IFS= read -r line; do
|
||||
if [[ $line =~ ^\[(.+)\]$ ]]; then
|
||||
current_section="${BASH_REMATCH[1]}"
|
||||
ini["$current_section"]=""
|
||||
elif [[ $line =~ ^([^=]+)=(.*)$ ]]; then
|
||||
local key="${BASH_REMATCH[1]}"
|
||||
local value="${BASH_REMATCH[2]}"
|
||||
if [ -n "$current_section" ]; then
|
||||
ini["$current_section,$key"]="$value"
|
||||
fi
|
||||
fi
|
||||
done < "$path_file"
|
||||
|
||||
# To use this function, you would need to pass the result by reference
|
||||
# and then access it in the calling function
|
||||
}
|
||||
|
||||
invoke_with_color_coded_output() {
|
||||
local command="$1"
|
||||
eval "$command" 2>&1 | while IFS= read -r line; do
|
||||
if [[ "$line" =~ [Ee]rror ]]; then
|
||||
echo -e "\033[0;31m\t$line\033[0m" # Red for errors
|
||||
elif [[ "$line" =~ [Ww]arning ]]; then
|
||||
echo -e "\033[0;33m\t$line\033[0m" # Yellow for warnings
|
||||
else
|
||||
echo -e "\033[0;37m\t$line\033[0m" # White for other output
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
update_git_repo() {
|
||||
local path="$1"
|
||||
local url="$2"
|
||||
local build_command="$3"
|
||||
|
||||
if [ -z "$build_command" ]; then
|
||||
echo "Attempted to call update_git_repo without build_command specified"
|
||||
return
|
||||
fi
|
||||
|
||||
local repo_name=$(basename "$url" .git)
|
||||
|
||||
local last_built_commit="$path_build/last_built_commit_$repo_name.txt"
|
||||
if [ ! -d "$path" ]; then
|
||||
echo "Cloning repo from $url to $path"
|
||||
git clone "$url" "$path"
|
||||
|
||||
echo "Building $url"
|
||||
pushd "$path" > /dev/null
|
||||
eval "$build_command"
|
||||
popd > /dev/null
|
||||
|
||||
git -C "$path" rev-parse HEAD > "$last_built_commit"
|
||||
binaries_dirty=true
|
||||
echo
|
||||
return
|
||||
fi
|
||||
|
||||
git -C "$path" fetch
|
||||
local latest_commit_hash=$(git -C "$path" rev-parse '@{u}')
|
||||
local last_built_hash=""
|
||||
[ -f "$last_built_commit" ] && last_built_hash=$(cat "$last_built_commit")
|
||||
|
||||
if [ "$latest_commit_hash" = "$last_built_hash" ]; then
|
||||
echo
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Build out of date for: $path, updating"
|
||||
echo 'Pulling...'
|
||||
git -C "$path" pull
|
||||
|
||||
echo "Building $url"
|
||||
pushd "$path" > /dev/null
|
||||
eval "$build_command"
|
||||
popd > /dev/null
|
||||
|
||||
echo "$latest_commit_hash" > "$last_built_commit"
|
||||
binaries_dirty=true
|
||||
echo
|
||||
}
|
||||
|
||||
verify_path() {
|
||||
local path="$1"
|
||||
if [ -d "$path" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$path"
|
||||
return 1
|
||||
}
|
4
thirdparty/sokol-tools/.gitignore
vendored
Normal file
4
thirdparty/sokol-tools/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.vscode/
|
||||
.zig-cache/
|
||||
zig-out/
|
||||
*.pyc
|
21
thirdparty/sokol-tools/LICENSE
vendored
Normal file
21
thirdparty/sokol-tools/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Andre Weissflog
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
thirdparty/sokol-tools/README.md
vendored
Normal file
2
thirdparty/sokol-tools/README.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# sokol-tools-bin
|
||||
Binaries and fips integration for https://github.com/floooh/sokol-tools
|
2
thirdparty/sokol-tools/bin/linux/readme.txt
vendored
Normal file
2
thirdparty/sokol-tools/bin/linux/readme.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Precompiled binaries for Linux go here (64-bit statically linked).
|
||||
|
BIN
thirdparty/sokol-tools/bin/linux/sokol-shdc
vendored
Normal file
BIN
thirdparty/sokol-tools/bin/linux/sokol-shdc
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol-tools/bin/linux_arm64/sokol-shdc
vendored
Normal file
BIN
thirdparty/sokol-tools/bin/linux_arm64/sokol-shdc
vendored
Normal file
Binary file not shown.
2
thirdparty/sokol-tools/bin/osx/readme.txt
vendored
Normal file
2
thirdparty/sokol-tools/bin/osx/readme.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Precompiled binaries for macOS go here.
|
||||
|
BIN
thirdparty/sokol-tools/bin/osx/sokol-shdc
vendored
Normal file
BIN
thirdparty/sokol-tools/bin/osx/sokol-shdc
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol-tools/bin/osx_arm64/sokol-shdc
vendored
Normal file
BIN
thirdparty/sokol-tools/bin/osx_arm64/sokol-shdc
vendored
Normal file
Binary file not shown.
2
thirdparty/sokol-tools/bin/win32/readme.txt
vendored
Normal file
2
thirdparty/sokol-tools/bin/win32/readme.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Precompiled binaries for Windows (64-bit) go here.
|
||||
|
BIN
thirdparty/sokol-tools/bin/win32/sokol-shdc.exe
vendored
Normal file
BIN
thirdparty/sokol-tools/bin/win32/sokol-shdc.exe
vendored
Normal file
Binary file not shown.
143
thirdparty/sokol-tools/build.zig
vendored
Normal file
143
thirdparty/sokol-tools/build.zig
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
//! Helper code to invoke sokol-shdc from the Zig build system.
|
||||
//! See https://github.com/floooh/sokol-zig for an example
|
||||
//! of how to use sokol-tools-bin as a lazy dependency and
|
||||
//! compile shaders (search for `shdc.compile` in the sokol-zig build.zig)
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Build = std.Build;
|
||||
|
||||
pub const Options = struct {
|
||||
dep_shdc: *Build.Dependency,
|
||||
input: Build.LazyPath,
|
||||
output: Build.LazyPath,
|
||||
slang: Slang,
|
||||
format: Format = .sokol_zig,
|
||||
tmp_dir: ?Build.LazyPath = null,
|
||||
defines: ?[][]const u8 = null,
|
||||
module: ?[]const u8 = null,
|
||||
reflection: bool = false,
|
||||
bytecode: bool = false,
|
||||
dump: bool = false,
|
||||
genver: ?[]const u8 = null,
|
||||
ifdef: bool = false,
|
||||
noifdef: bool = false,
|
||||
save_intermediate_spirv: bool = false,
|
||||
no_log_cmdline: bool = true,
|
||||
};
|
||||
|
||||
pub fn compile(b: *Build, opts: Options) !*Build.Step.Run {
|
||||
const shdc_path = try getShdcLazyPath(opts.dep_shdc);
|
||||
const args = try optsToArgs(opts, b, shdc_path);
|
||||
var step = b.addSystemCommand(args);
|
||||
step.addFileArg(opts.input);
|
||||
return step;
|
||||
}
|
||||
|
||||
/// target shader languages
|
||||
/// NOTE: make sure that field names match the cmdline arg string
|
||||
pub const Slang = packed struct(u10) {
|
||||
glsl410: bool = false,
|
||||
glsl430: bool = false,
|
||||
glsl300es: bool = false,
|
||||
glsl310es: bool = false,
|
||||
hlsl4: bool = false,
|
||||
hlsl5: bool = false,
|
||||
metal_macos: bool = false,
|
||||
metal_ios: bool = false,
|
||||
metal_sim: bool = false,
|
||||
wgsl: bool = false,
|
||||
};
|
||||
|
||||
fn slangToString(slang: Slang, a: Allocator) ![]const u8 {
|
||||
var strings: [16][]const u8 = undefined;
|
||||
var num_strings: usize = 0;
|
||||
inline for (std.meta.fields(Slang)) |field| {
|
||||
if (@field(slang, field.name)) {
|
||||
strings[num_strings] = field.name;
|
||||
num_strings += 1;
|
||||
}
|
||||
}
|
||||
return std.mem.join(a, ":", strings[0..num_strings]);
|
||||
}
|
||||
|
||||
/// the code-generation target language
|
||||
/// NOTE: make sure that the item names match the cmdline arg string
|
||||
pub const Format = enum {
|
||||
sokol,
|
||||
sokol_impl,
|
||||
sokol_zig,
|
||||
sokol_nim,
|
||||
sokol_odin,
|
||||
sokol_rust,
|
||||
sokol_d,
|
||||
sokol_jai,
|
||||
};
|
||||
|
||||
fn formatToString(f: Format) []const u8 {
|
||||
return @tagName(f);
|
||||
}
|
||||
|
||||
fn getShdcLazyPath(dep_shdc: *Build.Dependency) !Build.LazyPath {
|
||||
const intel = builtin.cpu.arch.isX86();
|
||||
const opt_sub_path: ?[]const u8 = switch (builtin.os.tag) {
|
||||
.windows => "bin/win32/sokol-shdc.exe",
|
||||
.linux => if (intel) "bin/linux/sokol-shdc" else "bin/linux_arm64/sokol-shdc",
|
||||
.macos => if (intel) "bin/osx/sokol-shdc" else "bin/osx_arm64/sokol-shdc",
|
||||
else => null,
|
||||
};
|
||||
if (opt_sub_path) |sub_path| {
|
||||
return dep_shdc.path(sub_path);
|
||||
} else {
|
||||
return error.ShdcUnsupportedPlatform;
|
||||
}
|
||||
}
|
||||
|
||||
fn optsToArgs(opts: Options, b: *Build, tool_path: Build.LazyPath) ![]const []const u8 {
|
||||
const a = b.allocator;
|
||||
var arr: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||
try arr.append(a, tool_path.getPath(b));
|
||||
try arr.appendSlice(a, &.{ "-o", opts.output.getPath(b) });
|
||||
try arr.appendSlice(a, &.{ "-l", try slangToString(opts.slang, a) });
|
||||
try arr.appendSlice(a, &.{ "-f", formatToString(opts.format) });
|
||||
if (opts.tmp_dir) |tmp_dir| {
|
||||
try arr.appendSlice(a, &.{ "--tmpdir", tmp_dir.getPath(b) });
|
||||
}
|
||||
if (opts.defines) |defines| {
|
||||
try arr.appendSlice(a, &.{ "--defines", try std.mem.join(a, ":", defines) });
|
||||
}
|
||||
if (opts.module) |module| {
|
||||
try arr.appendSlice(a, &.{ "--module", b.dupe(module) });
|
||||
}
|
||||
if (opts.reflection) {
|
||||
try arr.append(a, "--reflection");
|
||||
}
|
||||
if (opts.bytecode) {
|
||||
try arr.append(a, "--bytecode");
|
||||
}
|
||||
if (opts.dump) {
|
||||
try arr.append(a, "--dump");
|
||||
}
|
||||
if (opts.genver) |genver| {
|
||||
try arr.appendSlice(a, &.{ "--genver", b.dupe(genver) });
|
||||
}
|
||||
if (opts.ifdef) {
|
||||
try arr.append(a, "--ifdef");
|
||||
}
|
||||
if (opts.noifdef) {
|
||||
try arr.append(a, "--noifdef");
|
||||
}
|
||||
if (opts.save_intermediate_spirv) {
|
||||
try arr.append(a, "--save-intermediate-spirv");
|
||||
}
|
||||
if (opts.no_log_cmdline) {
|
||||
try arr.append(a, "--no-log-cmdline");
|
||||
}
|
||||
// important: keep this last
|
||||
try arr.append(a, "-i");
|
||||
return arr.toOwnedSlice(a);
|
||||
}
|
||||
|
||||
pub fn build(b: *Build) void {
|
||||
_ = b;
|
||||
}
|
7
thirdparty/sokol-tools/build.zig.zon
vendored
Normal file
7
thirdparty/sokol-tools/build.zig.zon
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
.{
|
||||
.name = .sokolshdc,
|
||||
.fingerprint = 0xe0596dde0e9962af,
|
||||
.version = "0.1.0",
|
||||
.minimum_zig_version = "0.14.0",
|
||||
.paths = .{ "bin", "build.zig", "build.zig.zon" },
|
||||
}
|
62
thirdparty/sokol-tools/fips-files/generators/SokolShader.py
vendored
Normal file
62
thirdparty/sokol-tools/fips-files/generators/SokolShader.py
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# SokolShader.py
|
||||
#
|
||||
# Fips code-generator script for invoking sokol-shdc during the build.
|
||||
#
|
||||
# Use the cmake macro 'sokol_shader([glsl-file] [shader-dialects])' inside a
|
||||
# fips target (fips_begin_* / fips_end_*) to hook the code-generation
|
||||
# build job into the build process.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
Version = 5
|
||||
|
||||
import os, platform, subprocess
|
||||
import genutil as util
|
||||
from mod import log
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def find_shdc():
|
||||
shdc_path = os.path.dirname(os.path.abspath(__file__))
|
||||
shdc_path += '/../../bin/'
|
||||
if platform.system() == 'Windows':
|
||||
shdc_path += 'win32/'
|
||||
elif platform.system() == 'Darwin':
|
||||
if platform.machine() == 'arm64':
|
||||
shdc_path += 'osx_arm64/'
|
||||
else:
|
||||
shdc_path += 'osx/'
|
||||
elif platform.system() == 'Linux':
|
||||
if platform.machine() in ['aarch64', 'arm64']:
|
||||
shdc_path += 'linux_arm64/'
|
||||
else:
|
||||
shdc_path += 'linux/'
|
||||
else:
|
||||
log.error('Unknown host system {}'.format(platform.system()))
|
||||
return shdc_path + 'sokol-shdc'
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def generate(input, out_src, out_hdr, args):
|
||||
errfmt = 'msvc' if args['compiler']=='MSVC' else 'gcc'
|
||||
if util.isDirty(Version, [input], [out_hdr]):
|
||||
print('## sokol-shdc: {} {} {}'.format(input, out_hdr, str(args)))
|
||||
cmd = [find_shdc(),
|
||||
'--input', input,
|
||||
'--output', out_hdr,
|
||||
'--slang', args['slang'],
|
||||
'--genver', str(Version),
|
||||
'--errfmt', errfmt,
|
||||
'--format', 'sokol']
|
||||
if 'defines' in args:
|
||||
cmd.extend(['--defines', args['defines']])
|
||||
if 'module' in args:
|
||||
cmd.extend(['--module', args['module']])
|
||||
if 'reflection' in args:
|
||||
if args['reflection']:
|
||||
cmd.extend(['--reflection'])
|
||||
if 'debuggable' in args and args['debuggable']:
|
||||
pass
|
||||
else:
|
||||
cmd.extend(['--bytecode'])
|
||||
res = subprocess.call(cmd)
|
||||
if res != 0:
|
||||
log.error('sokol-shdc returned with error code {}'.format(res))
|
25
thirdparty/sokol-tools/fips-files/include.cmake
vendored
Normal file
25
thirdparty/sokol-tools/fips-files/include.cmake
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
macro(sokol_shader shd slang)
|
||||
set(args "{slang: '${slang}', compiler: '${CMAKE_C_COMPILER_ID}' }")
|
||||
fips_generate(TYPE SokolShader FROM ${shd} HEADER ${shd}.h OUT_OF_SOURCE ARGS ${args})
|
||||
endmacro()
|
||||
|
||||
# special version which doesn't generate binary output, this allows shaders to be debugged
|
||||
macro(sokol_shader_debuggable shd slang)
|
||||
set(args "{slang: '${slang}', compiler: '${CMAKE_C_COMPILER_ID}', debuggable: true }")
|
||||
fips_generate(TYPE SokolShader FROM ${shd} HEADER ${shd}.h OUT_OF_SOURCE ARGS ${args})
|
||||
endmacro()
|
||||
|
||||
macro(sokol_shader_variant shd slang module defines)
|
||||
set(args "{slang: '${slang}', compiler: '${CMAKE_C_COMPILER_ID}', defines: '${defines}', module: '${module}' }")
|
||||
fips_generate(TYPE SokolShader FROM ${shd} HEADER ${shd}.${module}.h OUT_OF_SOURCE ARGS ${args})
|
||||
endmacro()
|
||||
|
||||
macro(sokol_shader_with_reflection shd slang)
|
||||
set(args "{slang: '${slang}', compiler: '${CMAKE_C_COMPILER_ID}', reflection: true }")
|
||||
fips_generate(TYPE SokolShader FROM ${shd} HEADER ${shd}.h OUT_OF_SOURCE ARGS ${args})
|
||||
endmacro()
|
||||
|
||||
macro(sokol_shader_variant_with_reflection shd slang module defines)
|
||||
set(args "{slang: '${slang}', compiler: '${CMAKE_C_COMPILER_ID}', defines: '${defines}', module: '${module}', reflection: true }")
|
||||
fips_generate(TYPE SokolShader FROM ${shd} HEADER ${shd}.${module}.h OUT_OF_SOURCE ARGS ${args})
|
||||
endmacro()
|
3
thirdparty/sokol/.gitignore
vendored
Normal file
3
thirdparty/sokol/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.vscode/
|
||||
build/
|
||||
ols.json
|
12
thirdparty/sokol/CHANGELOG.md
vendored
Normal file
12
thirdparty/sokol/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
## CHANGELOG
|
||||
|
||||
> NOTE: this changelog is only for changes to the sokol-odin 'scaffolding'.
|
||||
For actual Sokol header changes, see the
|
||||
[sokol changelog](https://github.com/floooh/sokol/blob/master/CHANGELOG.md).
|
||||
|
||||
### 13-Apr-2024
|
||||
|
||||
Merged PR https://github.com/floooh/sokol-odin/pull/11, this changes the
|
||||
directory structure of the bindings repository, adds support to build
|
||||
the Windows bindings as a DLL and a couple of smaller things
|
||||
detailed here: https://github.com/floooh/sokol/pull/1023
|
22
thirdparty/sokol/LICENSE
vendored
Normal file
22
thirdparty/sokol/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2022 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
81
thirdparty/sokol/README.md
vendored
Normal file
81
thirdparty/sokol/README.md
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
[](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)
|
||||
|
||||
Auto-generated [Odin](https://github.com/odin-lang/odin) bindings for the [sokol headers](https://github.com/floooh/sokol).
|
||||
|
||||
To include sokol in your project you can copy the [sokol](sokol/) directory.
|
||||
|
||||
## BUILD
|
||||
|
||||
Supported platforms are: Windows, macOS, Linux (with X11)
|
||||
|
||||
On Linux install the following packages: libglu1-mesa-dev, mesa-common-dev, xorg-dev, libasound-dev
|
||||
(or generally: the dev packages required for X11, GL and ALSA development)
|
||||
|
||||
1. First build the required static link libraries:
|
||||
|
||||
```
|
||||
cd sokol
|
||||
# on macOS:
|
||||
./build_clibs_macos.sh
|
||||
# on Linux:
|
||||
./build_clibs_linux.sh
|
||||
# on Windows with MSVC (from a 'Visual Studio Developer Command Prompt')
|
||||
build_clibs_windows.cmd
|
||||
cd ..
|
||||
```
|
||||
|
||||
2. Create a build directory and cd into it:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
```
|
||||
|
||||
3. Build and run the samples:
|
||||
```
|
||||
odin run ../examples/clear -debug
|
||||
odin run ../examples/triangle -debug
|
||||
odin run ../examples/quad -debug
|
||||
odin run ../examples/bufferoffsets -debug
|
||||
odin run ../examples/cube -debug
|
||||
odin run ../examples/noninterleaved -debug
|
||||
odin run ../examples/texcube -debug
|
||||
odin run ../examples/shapes -debug
|
||||
odin run ../examples/offscreen -debug
|
||||
odin run ../examples/instancing -debug
|
||||
odin run ../examples/mrt -debug
|
||||
odin run ../examples/blend -debug
|
||||
odin run ../examples/debugtext -debug
|
||||
odin run ../examples/debugtext-print -debug
|
||||
odin run ../examples/debugtext-userfont -debug
|
||||
odin run ../examples/saudio -debug
|
||||
odin run ../examples/sgl -debug
|
||||
odin run ../examples/sgl-points -debug
|
||||
odin run ../examples/sgl-context -debug
|
||||
odin run ../examples/vertexpull -debug
|
||||
```
|
||||
|
||||
By default, the backend 3D API will be selected based on the target platform:
|
||||
|
||||
- macOS: Metal
|
||||
- Windows: D3D11
|
||||
- Linux: GL
|
||||
|
||||
To force the GL backend on macOS or Windows, build with ```-define:SOKOL_USE_GL=true```:
|
||||
|
||||
```
|
||||
odin run ../examples/clear -debug -define:SOKOL_USE_GL=true
|
||||
```
|
||||
|
||||
The ```clear``` sample prints the selected backend to the terminal:
|
||||
|
||||
```
|
||||
odin run ../examples/clear -debug -define:SOKOL_USE_GL=true
|
||||
>> using GL backend
|
||||
```
|
||||
|
||||
On Windows, you can get rid of the automatically opened terminal window
|
||||
by building with the ```-subsystem:windows``` option:
|
||||
|
||||
```
|
||||
odin build ../examples/clear -subsystem:windows
|
||||
```
|
2033
thirdparty/sokol/app/app.odin
vendored
Normal file
2033
thirdparty/sokol/app/app.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
thirdparty/sokol/app/sokol_app_windows_x64_d3d11_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/app/sokol_app_windows_x64_d3d11_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/app/sokol_app_windows_x64_d3d11_release.lib
vendored
Normal file
BIN
thirdparty/sokol/app/sokol_app_windows_x64_d3d11_release.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/app/sokol_app_windows_x64_gl_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/app/sokol_app_windows_x64_gl_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/app/sokol_app_windows_x64_gl_release.lib
vendored
Normal file
BIN
thirdparty/sokol/app/sokol_app_windows_x64_gl_release.lib
vendored
Normal file
Binary file not shown.
649
thirdparty/sokol/audio/audio.odin
vendored
Normal file
649
thirdparty/sokol/audio/audio.odin
vendored
Normal file
@@ -0,0 +1,649 @@
|
||||
// machine generated, do not edit
|
||||
|
||||
package sokol_audio
|
||||
|
||||
/*
|
||||
|
||||
sokol_audio.h -- cross-platform audio-streaming API
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_AUDIO_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines with your own implementations:
|
||||
|
||||
SOKOL_DUMMY_BACKEND - use a dummy backend
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_AUDIO_API_DECL- public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_AUDIO_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
SAUDIO_RING_MAX_SLOTS - max number of slots in the push-audio ring buffer (default 1024)
|
||||
SAUDIO_OSX_USE_SYSTEM_HEADERS - define this to force inclusion of system headers on
|
||||
macOS instead of using embedded CoreAudio declarations
|
||||
|
||||
If sokol_audio.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_AUDIO_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
Link with the following libraries:
|
||||
|
||||
- on macOS: AudioToolbox
|
||||
- on iOS: AudioToolbox, AVFoundation
|
||||
- on FreeBSD: asound
|
||||
- on Linux: asound
|
||||
- on Android: aaudio
|
||||
- on Windows with MSVC or Clang toolchain: no action needed, libs are defined in-source via pragma-comment-lib
|
||||
- on Windows with MINGW/MSYS2 gcc: compile with '-mwin32' and link with -lole32
|
||||
|
||||
FEATURE OVERVIEW
|
||||
================
|
||||
You provide a mono- or stereo-stream of 32-bit float samples, which
|
||||
Sokol Audio feeds into platform-specific audio backends:
|
||||
|
||||
- Windows: WASAPI
|
||||
- Linux: ALSA
|
||||
- FreeBSD: ALSA
|
||||
- macOS: CoreAudio
|
||||
- iOS: CoreAudio+AVAudioSession
|
||||
- emscripten: WebAudio with ScriptProcessorNode
|
||||
- Android: AAudio
|
||||
|
||||
Sokol Audio will not do any buffer mixing or volume control, if you have
|
||||
multiple independent input streams of sample data you need to perform the
|
||||
mixing yourself before forwarding the data to Sokol Audio.
|
||||
|
||||
There are two mutually exclusive ways to provide the sample data:
|
||||
|
||||
1. Callback model: You provide a callback function, which will be called
|
||||
when Sokol Audio needs new samples. On all platforms except emscripten,
|
||||
this function is called from a separate thread.
|
||||
2. Push model: Your code pushes small blocks of sample data from your
|
||||
main loop or a thread you created. The pushed data is stored in
|
||||
a ring buffer where it is pulled by the backend code when
|
||||
needed.
|
||||
|
||||
The callback model is preferred because it is the most direct way to
|
||||
feed sample data into the audio backends and also has less moving parts
|
||||
(there is no ring buffer between your code and the audio backend).
|
||||
|
||||
Sometimes it is not possible to generate the audio stream directly in a
|
||||
callback function running in a separate thread, for such cases Sokol Audio
|
||||
provides the push-model as a convenience.
|
||||
|
||||
SOKOL AUDIO, SOLOUD AND MINIAUDIO
|
||||
=================================
|
||||
The WASAPI, ALSA and CoreAudio backend code has been taken from the
|
||||
SoLoud library (with some modifications, so any bugs in there are most
|
||||
likely my fault). If you need a more fully-featured audio solution, check
|
||||
out SoLoud, it's excellent:
|
||||
|
||||
https://github.com/jarikomppa/soloud
|
||||
|
||||
Another alternative which feature-wise is somewhere inbetween SoLoud and
|
||||
sokol-audio might be MiniAudio:
|
||||
|
||||
https://github.com/mackron/miniaudio
|
||||
|
||||
GLOSSARY
|
||||
========
|
||||
- stream buffer:
|
||||
The internal audio data buffer, usually provided by the backend API. The
|
||||
size of the stream buffer defines the base latency, smaller buffers have
|
||||
lower latency but may cause audio glitches. Bigger buffers reduce or
|
||||
eliminate glitches, but have a higher base latency.
|
||||
|
||||
- stream callback:
|
||||
Optional callback function which is called by Sokol Audio when it
|
||||
needs new samples. On Windows, macOS/iOS and Linux, this is called in
|
||||
a separate thread, on WebAudio, this is called per-frame in the
|
||||
browser thread.
|
||||
|
||||
- channel:
|
||||
A discrete track of audio data, currently 1-channel (mono) and
|
||||
2-channel (stereo) is supported and tested.
|
||||
|
||||
- sample:
|
||||
The magnitude of an audio signal on one channel at a given time. In
|
||||
Sokol Audio, samples are 32-bit float numbers in the range -1.0 to
|
||||
+1.0.
|
||||
|
||||
- frame:
|
||||
The tightly packed set of samples for all channels at a given time.
|
||||
For mono 1 frame is 1 sample. For stereo, 1 frame is 2 samples.
|
||||
|
||||
- packet:
|
||||
In Sokol Audio, a small chunk of audio data that is moved from the
|
||||
main thread to the audio streaming thread in order to decouple the
|
||||
rate at which the main thread provides new audio data, and the
|
||||
streaming thread consuming audio data.
|
||||
|
||||
WORKING WITH SOKOL AUDIO
|
||||
========================
|
||||
First call saudio_setup() with your preferred audio playback options.
|
||||
In most cases you can stick with the default values, these provide
|
||||
a good balance between low-latency and glitch-free playback
|
||||
on all audio backends.
|
||||
|
||||
You should always provide a logging callback to be aware of any
|
||||
warnings and errors. The easiest way is to use sokol_log.h for this:
|
||||
|
||||
#include "sokol_log.h"
|
||||
// ...
|
||||
saudio_setup(&(saudio_desc){
|
||||
.logger = {
|
||||
.func = slog_func,
|
||||
}
|
||||
});
|
||||
|
||||
If you want to use the callback-model, you need to provide a stream
|
||||
callback function either in saudio_desc.stream_cb or saudio_desc.stream_userdata_cb,
|
||||
otherwise keep both function pointers zero-initialized.
|
||||
|
||||
Use push model and default playback parameters:
|
||||
|
||||
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
|
||||
|
||||
Use stream callback model and default playback parameters:
|
||||
|
||||
saudio_setup(&(saudio_desc){
|
||||
.stream_cb = my_stream_callback
|
||||
.logger.func = slog_func,
|
||||
});
|
||||
|
||||
The standard stream callback doesn't have a user data argument, if you want
|
||||
that, use the alternative stream_userdata_cb and also set the user_data pointer:
|
||||
|
||||
saudio_setup(&(saudio_desc){
|
||||
.stream_userdata_cb = my_stream_callback,
|
||||
.user_data = &my_data
|
||||
.logger.func = slog_func,
|
||||
});
|
||||
|
||||
The following playback parameters can be provided through the
|
||||
saudio_desc struct:
|
||||
|
||||
General parameters (both for stream-callback and push-model):
|
||||
|
||||
int sample_rate -- the sample rate in Hz, default: 44100
|
||||
int num_channels -- number of channels, default: 1 (mono)
|
||||
int buffer_frames -- number of frames in streaming buffer, default: 2048
|
||||
|
||||
The stream callback prototype (either with or without userdata):
|
||||
|
||||
void (*stream_cb)(float* buffer, int num_frames, int num_channels)
|
||||
void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data)
|
||||
Function pointer to the user-provide stream callback.
|
||||
|
||||
Push-model parameters:
|
||||
|
||||
int packet_frames -- number of frames in a packet, default: 128
|
||||
int num_packets -- number of packets in ring buffer, default: 64
|
||||
|
||||
The sample_rate and num_channels parameters are only hints for the audio
|
||||
backend, it isn't guaranteed that those are the values used for actual
|
||||
playback.
|
||||
|
||||
To get the actual parameters, call the following functions after
|
||||
saudio_setup():
|
||||
|
||||
int saudio_sample_rate(void)
|
||||
int saudio_channels(void);
|
||||
|
||||
It's unlikely that the number of channels will be different than requested,
|
||||
but a different sample rate isn't uncommon.
|
||||
|
||||
(NOTE: there's an yet unsolved issue when an audio backend might switch
|
||||
to a different sample rate when switching output devices, for instance
|
||||
plugging in a bluetooth headset, this case is currently not handled in
|
||||
Sokol Audio).
|
||||
|
||||
You can check if audio initialization was successful with
|
||||
saudio_isvalid(). If backend initialization failed for some reason
|
||||
(for instance when there's no audio device in the machine), this
|
||||
will return false. Not checking for success won't do any harm, all
|
||||
Sokol Audio function will silently fail when called after initialization
|
||||
has failed, so apart from missing audio output, nothing bad will happen.
|
||||
|
||||
Before your application exits, you should call
|
||||
|
||||
saudio_shutdown();
|
||||
|
||||
This stops the audio thread (on Linux, Windows and macOS/iOS) and
|
||||
properly shuts down the audio backend.
|
||||
|
||||
THE STREAM CALLBACK MODEL
|
||||
=========================
|
||||
To use Sokol Audio in stream-callback-mode, provide a callback function
|
||||
like this in the saudio_desc struct when calling saudio_setup():
|
||||
|
||||
void stream_cb(float* buffer, int num_frames, int num_channels) {
|
||||
...
|
||||
}
|
||||
|
||||
Or the alternative version with a user-data argument:
|
||||
|
||||
void stream_userdata_cb(float* buffer, int num_frames, int num_channels, void* user_data) {
|
||||
my_data_t* my_data = (my_data_t*) user_data;
|
||||
...
|
||||
}
|
||||
|
||||
The job of the callback function is to fill the *buffer* with 32-bit
|
||||
float sample values.
|
||||
|
||||
To output silence, fill the buffer with zeros:
|
||||
|
||||
void stream_cb(float* buffer, int num_frames, int num_channels) {
|
||||
const int num_samples = num_frames * num_channels;
|
||||
for (int i = 0; i < num_samples; i++) {
|
||||
buffer[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
For stereo output (num_channels == 2), the samples for the left
|
||||
and right channel are interleaved:
|
||||
|
||||
void stream_cb(float* buffer, int num_frames, int num_channels) {
|
||||
assert(2 == num_channels);
|
||||
for (int i = 0; i < num_frames; i++) {
|
||||
buffer[2*i + 0] = ...; // left channel
|
||||
buffer[2*i + 1] = ...; // right channel
|
||||
}
|
||||
}
|
||||
|
||||
Please keep in mind that the stream callback function is running in a
|
||||
separate thread, if you need to share data with the main thread you need
|
||||
to take care yourself to make the access to the shared data thread-safe!
|
||||
|
||||
THE PUSH MODEL
|
||||
==============
|
||||
To use the push-model for providing audio data, simply don't set (keep
|
||||
zero-initialized) the stream_cb field in the saudio_desc struct when
|
||||
calling saudio_setup().
|
||||
|
||||
To provide sample data with the push model, call the saudio_push()
|
||||
function at regular intervals (for instance once per frame). You can
|
||||
call the saudio_expect() function to ask Sokol Audio how much room is
|
||||
in the ring buffer, but if you provide a continuous stream of data
|
||||
at the right sample rate, saudio_expect() isn't required (it's a simple
|
||||
way to sync/throttle your sample generation code with the playback
|
||||
rate though).
|
||||
|
||||
With saudio_push() you may need to maintain your own intermediate sample
|
||||
buffer, since pushing individual sample values isn't very efficient.
|
||||
The following example is from the MOD player sample in
|
||||
sokol-samples (https://github.com/floooh/sokol-samples):
|
||||
|
||||
const int num_frames = saudio_expect();
|
||||
if (num_frames > 0) {
|
||||
const int num_samples = num_frames * saudio_channels();
|
||||
read_samples(flt_buf, num_samples);
|
||||
saudio_push(flt_buf, num_frames);
|
||||
}
|
||||
|
||||
Another option is to ignore saudio_expect(), and just push samples as they
|
||||
are generated in small batches. In this case you *need* to generate the
|
||||
samples at the right sample rate:
|
||||
|
||||
The following example is taken from the Tiny Emulators project
|
||||
(https://github.com/floooh/chips-test), this is for mono playback,
|
||||
so (num_samples == num_frames):
|
||||
|
||||
// tick the sound generator
|
||||
if (ay38910_tick(&sys->psg)) {
|
||||
// new sample is ready
|
||||
sys->sample_buffer[sys->sample_pos++] = sys->psg.sample;
|
||||
if (sys->sample_pos == sys->num_samples) {
|
||||
// new sample packet is ready
|
||||
saudio_push(sys->sample_buffer, sys->num_samples);
|
||||
sys->sample_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
THE WEBAUDIO BACKEND
|
||||
====================
|
||||
The WebAudio backend is currently using a ScriptProcessorNode callback to
|
||||
feed the sample data into WebAudio. ScriptProcessorNode has been
|
||||
deprecated for a while because it is running from the main thread, with
|
||||
the default initialization parameters it works 'pretty well' though.
|
||||
Ultimately Sokol Audio will use Audio Worklets, but this requires a few
|
||||
more things to fall into place (Audio Worklets implemented everywhere,
|
||||
SharedArrayBuffers enabled again, and I need to figure out a 'low-cost'
|
||||
solution in terms of implementation effort, since Audio Worklets are
|
||||
a lot more complex than ScriptProcessorNode if the audio data needs to come
|
||||
from the main thread).
|
||||
|
||||
The WebAudio backend is automatically selected when compiling for
|
||||
emscripten (__EMSCRIPTEN__ define exists).
|
||||
|
||||
https://developers.google.com/web/updates/2017/12/audio-worklet
|
||||
https://developers.google.com/web/updates/2018/06/audio-worklet-design-pattern
|
||||
|
||||
"Blob URLs": https://www.html5rocks.com/en/tutorials/workers/basics/
|
||||
|
||||
Also see: https://blog.paul.cx/post/a-wait-free-spsc-ringbuffer-for-the-web/
|
||||
|
||||
THE COREAUDIO BACKEND
|
||||
=====================
|
||||
The CoreAudio backend is selected on macOS and iOS (__APPLE__ is defined).
|
||||
Since the CoreAudio API is implemented in C (not Objective-C) on macOS the
|
||||
implementation part of Sokol Audio can be included into a C source file.
|
||||
|
||||
However on iOS, Sokol Audio must be compiled as Objective-C due to it's
|
||||
reliance on the AVAudioSession object. The iOS code path support both
|
||||
being compiled with or without ARC (Automatic Reference Counting).
|
||||
|
||||
For thread synchronisation, the CoreAudio backend will use the
|
||||
pthread_mutex_* functions.
|
||||
|
||||
The incoming floating point samples will be directly forwarded to
|
||||
CoreAudio without further conversion.
|
||||
|
||||
macOS and iOS applications that use Sokol Audio need to link with
|
||||
the AudioToolbox framework.
|
||||
|
||||
THE WASAPI BACKEND
|
||||
==================
|
||||
The WASAPI backend is automatically selected when compiling on Windows
|
||||
(_WIN32 is defined).
|
||||
|
||||
For thread synchronisation a Win32 critical section is used.
|
||||
|
||||
WASAPI may use a different size for its own streaming buffer then requested,
|
||||
so the base latency may be slightly bigger. The current backend implementation
|
||||
converts the incoming floating point sample values to signed 16-bit
|
||||
integers.
|
||||
|
||||
The required Windows system DLLs are linked with #pragma comment(lib, ...),
|
||||
so you shouldn't need to add additional linker libs in the build process
|
||||
(otherwise this is a bug which should be fixed in sokol_audio.h).
|
||||
|
||||
THE ALSA BACKEND
|
||||
================
|
||||
The ALSA backend is automatically selected when compiling on Linux
|
||||
('linux' is defined).
|
||||
|
||||
For thread synchronisation, the pthread_mutex_* functions are used.
|
||||
|
||||
Samples are directly forwarded to ALSA in 32-bit float format, no
|
||||
further conversion is taking place.
|
||||
|
||||
You need to link with the 'asound' library, and the <alsa/asoundlib.h>
|
||||
header must be present (usually both are installed with some sort
|
||||
of ALSA development package).
|
||||
|
||||
|
||||
MEMORY ALLOCATION OVERRIDE
|
||||
==========================
|
||||
You can override the memory allocation functions at initialization time
|
||||
like this:
|
||||
|
||||
void* my_alloc(size_t size, void* user_data) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void my_free(void* ptr, void* user_data) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
...
|
||||
saudio_setup(&(saudio_desc){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
...
|
||||
|
||||
If no overrides are provided, malloc and free will be used.
|
||||
|
||||
This only affects memory allocation calls done by sokol_audio.h
|
||||
itself though, not any allocations in OS libraries.
|
||||
|
||||
Memory allocation will only happen on the same thread where saudio_setup()
|
||||
was called, so you don't need to worry about thread-safety.
|
||||
|
||||
|
||||
ERROR REPORTING AND LOGGING
|
||||
===========================
|
||||
To get any logging information at all you need to provide a logging callback in the setup call
|
||||
the easiest way is to use sokol_log.h:
|
||||
|
||||
#include "sokol_log.h"
|
||||
|
||||
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
|
||||
|
||||
To override logging with your own callback, first write a logging function like this:
|
||||
|
||||
void my_log(const char* tag, // e.g. 'saudio'
|
||||
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
|
||||
uint32_t log_item_id, // SAUDIO_LOGITEM_*
|
||||
const char* message_or_null, // a message string, may be nullptr in release mode
|
||||
uint32_t line_nr, // line number in sokol_audio.h
|
||||
const char* filename_or_null, // source filename, may be nullptr in release mode
|
||||
void* user_data)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
...and then setup sokol-audio like this:
|
||||
|
||||
saudio_setup(&(saudio_desc){
|
||||
.logger = {
|
||||
.func = my_log,
|
||||
.user_data = my_user_data,
|
||||
}
|
||||
});
|
||||
|
||||
The provided logging function must be reentrant (e.g. be callable from
|
||||
different threads).
|
||||
|
||||
If you don't want to provide your own custom logger it is highly recommended to use
|
||||
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
|
||||
errors.
|
||||
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
*/
|
||||
|
||||
import "core:c"
|
||||
|
||||
_ :: c
|
||||
|
||||
SOKOL_DEBUG :: #config(SOKOL_DEBUG, ODIN_DEBUG)
|
||||
|
||||
DEBUG :: #config(SOKOL_AUDIO_DEBUG, SOKOL_DEBUG)
|
||||
USE_GL :: #config(SOKOL_USE_GL, false)
|
||||
USE_DLL :: #config(SOKOL_DLL, false)
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
when USE_DLL {
|
||||
when USE_GL {
|
||||
when DEBUG { foreign import sokol_audio_clib { "../sokol_dll_windows_x64_gl_debug.lib" } }
|
||||
else { foreign import sokol_audio_clib { "../sokol_dll_windows_x64_gl_release.lib" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_audio_clib { "../sokol_dll_windows_x64_d3d11_debug.lib" } }
|
||||
else { foreign import sokol_audio_clib { "../sokol_dll_windows_x64_d3d11_release.lib" } }
|
||||
}
|
||||
} else {
|
||||
when USE_GL {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_windows_x64_gl_debug.lib" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_windows_x64_gl_release.lib" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_windows_x64_d3d11_debug.lib" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_windows_x64_d3d11_release.lib" } }
|
||||
}
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
when USE_DLL {
|
||||
when USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_arm64_gl_release.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_x64_gl_debug.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_x64_gl_release.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_arm64_metal_release.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_x64_metal_debug.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_audio_clib { "../dylib/sokol_dylib_macos_x64_metal_release.dylib" } }
|
||||
} else {
|
||||
when USE_GL {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_macos_arm64_gl_debug.a", "system:AudioToolbox.framework" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_macos_arm64_gl_release.a", "system:AudioToolbox.framework" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_macos_x64_gl_debug.a", "system:AudioToolbox.framework" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_macos_x64_gl_release.a", "system:AudioToolbox.framework" } }
|
||||
}
|
||||
} else {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_macos_arm64_metal_debug.a", "system:AudioToolbox.framework" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_macos_arm64_metal_release.a", "system:AudioToolbox.framework" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_macos_x64_metal_debug.a", "system:AudioToolbox.framework" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_macos_x64_metal_release.a", "system:AudioToolbox.framework" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else when ODIN_OS == .Linux {
|
||||
when USE_DLL {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_linux_x64_gl_debug.so", "system:asound", "system:dl", "system:pthread" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_linux_x64_gl_release.so", "system:asound", "system:dl", "system:pthread" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_audio_clib { "sokol_audio_linux_x64_gl_debug.a", "system:asound", "system:dl", "system:pthread" } }
|
||||
else { foreign import sokol_audio_clib { "sokol_audio_linux_x64_gl_release.a", "system:asound", "system:dl", "system:pthread" } }
|
||||
}
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
// Feed sokol_audio_wasm_gl_debug.a or sokol_audio_wasm_gl_release.a into emscripten compiler.
|
||||
foreign import sokol_audio_clib { "env.o" }
|
||||
} else {
|
||||
#panic("This OS is currently not supported")
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="saudio_")
|
||||
foreign sokol_audio_clib {
|
||||
// setup sokol-audio
|
||||
setup :: proc(#by_ptr desc: Desc) ---
|
||||
// shutdown sokol-audio
|
||||
shutdown :: proc() ---
|
||||
// true after setup if audio backend was successfully initialized
|
||||
isvalid :: proc() -> bool ---
|
||||
// return the saudio_desc.user_data pointer
|
||||
userdata :: proc() -> rawptr ---
|
||||
// return a copy of the original saudio_desc struct
|
||||
query_desc :: proc() -> Desc ---
|
||||
// actual sample rate
|
||||
sample_rate :: proc() -> c.int ---
|
||||
// return actual backend buffer size in number of frames
|
||||
buffer_frames :: proc() -> c.int ---
|
||||
// actual number of channels
|
||||
channels :: proc() -> c.int ---
|
||||
// return true if audio context is currently suspended (only in WebAudio backend, all other backends return false)
|
||||
suspended :: proc() -> bool ---
|
||||
// get current number of frames to fill packet queue
|
||||
expect :: proc() -> c.int ---
|
||||
// push sample frames from main thread, returns number of frames actually pushed
|
||||
push :: proc(frames: ^f32, #any_int num_frames: c.int) -> c.int ---
|
||||
}
|
||||
|
||||
Log_Item :: enum i32 {
|
||||
OK,
|
||||
MALLOC_FAILED,
|
||||
ALSA_SND_PCM_OPEN_FAILED,
|
||||
ALSA_FLOAT_SAMPLES_NOT_SUPPORTED,
|
||||
ALSA_REQUESTED_BUFFER_SIZE_NOT_SUPPORTED,
|
||||
ALSA_REQUESTED_CHANNEL_COUNT_NOT_SUPPORTED,
|
||||
ALSA_SND_PCM_HW_PARAMS_SET_RATE_NEAR_FAILED,
|
||||
ALSA_SND_PCM_HW_PARAMS_FAILED,
|
||||
ALSA_PTHREAD_CREATE_FAILED,
|
||||
WASAPI_CREATE_EVENT_FAILED,
|
||||
WASAPI_CREATE_DEVICE_ENUMERATOR_FAILED,
|
||||
WASAPI_GET_DEFAULT_AUDIO_ENDPOINT_FAILED,
|
||||
WASAPI_DEVICE_ACTIVATE_FAILED,
|
||||
WASAPI_AUDIO_CLIENT_INITIALIZE_FAILED,
|
||||
WASAPI_AUDIO_CLIENT_GET_BUFFER_SIZE_FAILED,
|
||||
WASAPI_AUDIO_CLIENT_GET_SERVICE_FAILED,
|
||||
WASAPI_AUDIO_CLIENT_SET_EVENT_HANDLE_FAILED,
|
||||
WASAPI_CREATE_THREAD_FAILED,
|
||||
AAUDIO_STREAMBUILDER_OPEN_STREAM_FAILED,
|
||||
AAUDIO_PTHREAD_CREATE_FAILED,
|
||||
AAUDIO_RESTARTING_STREAM_AFTER_ERROR,
|
||||
USING_AAUDIO_BACKEND,
|
||||
AAUDIO_CREATE_STREAMBUILDER_FAILED,
|
||||
COREAUDIO_NEW_OUTPUT_FAILED,
|
||||
COREAUDIO_ALLOCATE_BUFFER_FAILED,
|
||||
COREAUDIO_START_FAILED,
|
||||
BACKEND_BUFFER_SIZE_ISNT_MULTIPLE_OF_PACKET_SIZE,
|
||||
}
|
||||
|
||||
/*
|
||||
saudio_logger
|
||||
|
||||
Used in saudio_desc to provide a custom logging and error reporting
|
||||
callback to sokol-audio.
|
||||
*/
|
||||
Logger :: struct {
|
||||
func : proc "c" (a0: cstring, a1: u32, a2: u32, a3: cstring, a4: u32, a5: cstring, a6: rawptr),
|
||||
user_data : rawptr,
|
||||
}
|
||||
|
||||
/*
|
||||
saudio_allocator
|
||||
|
||||
Used in saudio_desc to provide custom memory-alloc and -free functions
|
||||
to sokol_audio.h. If memory management should be overridden, both the
|
||||
alloc_fn and free_fn function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
Allocator :: struct {
|
||||
alloc_fn : proc "c" (a0: c.size_t, a1: rawptr) -> rawptr,
|
||||
free_fn : proc "c" (a0: rawptr, a1: rawptr),
|
||||
user_data : rawptr,
|
||||
}
|
||||
|
||||
Desc :: struct {
|
||||
sample_rate : c.int,
|
||||
num_channels : c.int,
|
||||
buffer_frames : c.int,
|
||||
packet_frames : c.int,
|
||||
num_packets : c.int,
|
||||
stream_cb : proc "c" (a0: ^f32, a1: c.int, a2: c.int),
|
||||
stream_userdata_cb : proc "c" (a0: ^f32, a1: c.int, a2: c.int, a3: rawptr),
|
||||
user_data : rawptr,
|
||||
allocator : Allocator,
|
||||
logger : Logger,
|
||||
}
|
||||
|
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_d3d11_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_d3d11_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_d3d11_release.lib
vendored
Normal file
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_d3d11_release.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_gl_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_gl_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_gl_release.lib
vendored
Normal file
BIN
thirdparty/sokol/audio/sokol_audio_windows_x64_gl_release.lib
vendored
Normal file
Binary file not shown.
49
thirdparty/sokol/build_clibs_linux.sh
vendored
Normal file
49
thirdparty/sokol/build_clibs_linux.sh
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
set -e
|
||||
|
||||
build_lib_x64_release() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
# static
|
||||
cc -pthread -c -O2 -DNDEBUG -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
# shared
|
||||
cc -pthread -shared -O2 -fPIC -DNDEBUG -DIMPL -D$backend -o $dst.so c/$src.c
|
||||
}
|
||||
|
||||
build_lib_x64_debug() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
# static
|
||||
cc -pthread -c -g -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
# shared
|
||||
cc -pthread -shared -g -fPIC -DIMPL -D$backend -o $dst.so c/$src.c
|
||||
}
|
||||
|
||||
# x64 + GL + Release
|
||||
build_lib_x64_release sokol_log log/sokol_log_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_gfx gfx/sokol_gfx_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_app app/sokol_app_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_glue glue/sokol_glue_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_time time/sokol_time_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_audio audio/sokol_audio_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_shape shape/sokol_shape_linux_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_gl gl/sokol_gl_linux_x64_gl_release SOKOL_GLCORE
|
||||
|
||||
# x64 + GL + Debug
|
||||
build_lib_x64_debug sokol_log log/sokol_log_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_app app/sokol_app_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_glue glue/sokol_glue_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_time time/sokol_time_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_audio audio/sokol_audio_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_shape shape/sokol_shape_linux_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_gl gl/sokol_gl_linux_x64_gl_debug SOKOL_GLCORE
|
||||
|
||||
rm *.o
|
127
thirdparty/sokol/build_clibs_macos.sh
vendored
Normal file
127
thirdparty/sokol/build_clibs_macos.sh
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
set -e
|
||||
|
||||
build_lib_arm64_release() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -O2 -x objective-c -arch arm64 -DNDEBUG -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
}
|
||||
|
||||
build_lib_arm64_debug() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -g -x objective-c -arch arm64 -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
}
|
||||
|
||||
build_lib_x64_release() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -O2 -x objective-c -arch x86_64 -DNDEBUG -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
}
|
||||
|
||||
build_lib_x64_debug() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -g -x objective-c -arch x86_64 -DIMPL -D$backend c/$src.c
|
||||
ar rcs $dst.a $src.o
|
||||
}
|
||||
|
||||
# ARM + Metal + Release
|
||||
build_lib_arm64_release sokol_log log/sokol_log_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_gfx gfx/sokol_gfx_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_app app/sokol_app_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_glue glue/sokol_glue_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_time time/sokol_time_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_audio audio/sokol_audio_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_debugtext debugtext/sokol_debugtext_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_shape shape/sokol_shape_macos_arm64_metal_release SOKOL_METAL
|
||||
build_lib_arm64_release sokol_gl gl/sokol_gl_macos_arm64_metal_release SOKOL_METAL
|
||||
|
||||
# ARM + Metal + Debug
|
||||
build_lib_arm64_debug sokol_log log/sokol_log_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_gfx gfx/sokol_gfx_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_app app/sokol_app_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_glue glue/sokol_glue_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_time time/sokol_time_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_audio audio/sokol_audio_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_debugtext debugtext/sokol_debugtext_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_shape shape/sokol_shape_macos_arm64_metal_debug SOKOL_METAL
|
||||
build_lib_arm64_debug sokol_gl gl/sokol_gl_macos_arm64_metal_debug SOKOL_METAL
|
||||
|
||||
# x64 + Metal + Release
|
||||
build_lib_x64_release sokol_log log/sokol_log_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_gfx gfx/sokol_gfx_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_app app/sokol_app_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_glue glue/sokol_glue_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_time time/sokol_time_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_audio audio/sokol_audio_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_shape shape/sokol_shape_macos_x64_metal_release SOKOL_METAL
|
||||
build_lib_x64_release sokol_gl gl/sokol_gl_macos_x64_metal_release SOKOL_METAL
|
||||
|
||||
# x64 + Metal + Debug
|
||||
build_lib_x64_debug sokol_log log/sokol_log_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_app app/sokol_app_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_glue glue/sokol_glue_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_time time/sokol_time_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_audio audio/sokol_audio_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_shape shape/sokol_shape_macos_x64_metal_debug SOKOL_METAL
|
||||
build_lib_x64_debug sokol_gl gl/sokol_gl_macos_x64_metal_debug SOKOL_METAL
|
||||
|
||||
# ARM + GL + Release
|
||||
build_lib_arm64_release sokol_log log/sokol_log_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_gfx gfx/sokol_gfx_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_app app/sokol_app_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_glue glue/sokol_glue_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_time time/sokol_time_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_audio audio/sokol_audio_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_debugtext debugtext/sokol_debugtext_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_shape shape/sokol_shape_macos_arm64_gl_release SOKOL_GLCORE
|
||||
build_lib_arm64_release sokol_gl gl/sokol_gl_macos_arm64_gl_release SOKOL_GLCORE
|
||||
|
||||
# ARM + GL + Debug
|
||||
build_lib_arm64_debug sokol_log log/sokol_log_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_gfx gfx/sokol_gfx_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_app app/sokol_app_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_glue glue/sokol_glue_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_time time/sokol_time_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_audio audio/sokol_audio_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_debugtext debugtext/sokol_debugtext_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_shape shape/sokol_shape_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
build_lib_arm64_debug sokol_gl gl/sokol_gl_macos_arm64_gl_debug SOKOL_GLCORE
|
||||
|
||||
# x64 + GL + Release
|
||||
build_lib_x64_release sokol_log log/sokol_log_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_gfx gfx/sokol_gfx_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_app app/sokol_app_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_glue glue/sokol_glue_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_time time/sokol_time_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_audio audio/sokol_audio_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_shape shape/sokol_shape_macos_x64_gl_release SOKOL_GLCORE
|
||||
build_lib_x64_release sokol_gl gl/sokol_gl_macos_x64_gl_release SOKOL_GLCORE
|
||||
|
||||
# x64 + GL + Debug
|
||||
build_lib_x64_debug sokol_log log/sokol_log_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_app app/sokol_app_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_glue glue/sokol_glue_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_time time/sokol_time_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_audio audio/sokol_audio_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_shape shape/sokol_shape_macos_x64_gl_debug SOKOL_GLCORE
|
||||
build_lib_x64_debug sokol_gl gl/sokol_gl_macos_x64_gl_debug SOKOL_GLCORE
|
||||
|
||||
rm *.o
|
50
thirdparty/sokol/build_clibs_macos_dylib.sh
vendored
Normal file
50
thirdparty/sokol/build_clibs_macos_dylib.sh
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
set -e
|
||||
|
||||
FRAMEWORKS_METAL="-framework Metal -framework MetalKit"
|
||||
FRAMEWORKS_OPENGL="-framework OpenGL"
|
||||
FRAMEWORKS_CORE="-framework Foundation -framework CoreGraphics -framework Cocoa -framework QuartzCore -framework CoreAudio -framework AudioToolbox"
|
||||
|
||||
build_lib_release() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
arch=$4
|
||||
frameworks=""
|
||||
if [ $backend = "SOKOL_METAL" ]; then
|
||||
frameworks="${frameworks} ${FRAMEWORKS_METAL}"
|
||||
else
|
||||
frameworks="${frameworks} ${FRAMEWORKS_OPENGL}"
|
||||
fi
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -O2 -x objective-c -arch $arch -DNDEBUG -DIMPL -D$backend c/$src.c
|
||||
clang -dynamiclib -arch $arch $FRAMEWORKS_CORE $frameworks -o $dst.dylib $src.o $dep
|
||||
}
|
||||
|
||||
build_lib_debug() {
|
||||
src=$1
|
||||
dst=$2
|
||||
backend=$3
|
||||
arch=$4
|
||||
frameworks=""
|
||||
if [ $backend = "SOKOL_METAL" ]; then
|
||||
frameworks="${frameworks} ${FRAMEWORKS_METAL}"
|
||||
else
|
||||
frameworks="${frameworks} ${FRAMEWORKS_OPENGL}"
|
||||
fi
|
||||
echo $dst
|
||||
MACOSX_DEPLOYMENT_TARGET=10.13 clang -c -g -x objective-c -arch $arch -DIMPL -D$backend c/$src.c
|
||||
clang -dynamiclib -arch $arch $FRAMEWORKS_CORE $frameworks -o $dst.dylib $src.o $dep
|
||||
}
|
||||
|
||||
mkdir -p dylib
|
||||
|
||||
build_lib_release sokol dylib/sokol_dylib_macos_arm64_metal_release SOKOL_METAL arm64
|
||||
build_lib_debug sokol dylib/sokol_dylib_macos_arm64_metal_debug SOKOL_METAL arm64
|
||||
build_lib_release sokol dylib/sokol_dylib_macos_x64_metal_release SOKOL_METAL x86_64
|
||||
build_lib_debug sokol dylib/sokol_dylib_macos_x64_metal_debug SOKOL_METAL x86_64
|
||||
build_lib_release sokol dylib/sokol_dylib_macos_arm64_gl_release SOKOL_GLCORE arm64
|
||||
build_lib_debug sokol dylib/sokol_dylib_macos_arm64_gl_debug SOKOL_GLCORE arm64
|
||||
build_lib_release sokol dylib/sokol_dylib_macos_x64_gl_release SOKOL_GLCORE x86_64
|
||||
build_lib_debug sokol dylib/sokol_dylib_macos_x64_gl_debug SOKOL_GLCORE x86_64
|
||||
|
||||
rm *.o
|
19
thirdparty/sokol/build_clibs_wasm.bat
vendored
Normal file
19
thirdparty/sokol/build_clibs_wasm.bat
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
|
||||
set sources=log app gfx glue time audio debugtext shape gl
|
||||
|
||||
REM Debug
|
||||
for %%s in (%sources%) do (
|
||||
echo %%s\sokol_%%s_wasm_gl_debug.a
|
||||
call emcc -c -g -DIMPL -DSOKOL_GLES3 c\sokol_%%s.c
|
||||
call emar rcs %%s\sokol_%%s_wasm_gl_debug.a sokol_%%s.o
|
||||
del sokol_%%s.o
|
||||
)
|
||||
|
||||
REM Release
|
||||
for %%s in (%sources%) do (
|
||||
echo %%s\sokol_%%s_wasm_gl_release.a
|
||||
call emcc -c -O2 -DNDEBUG -DIMPL -DSOKOL_GLES3 c\sokol_%%s.c
|
||||
call emar rcs %%s\sokol_%%s_wasm_gl_release.a sokol_%%s.o
|
||||
del sokol_%%s.o
|
||||
)
|
20
thirdparty/sokol/build_clibs_wasm.sh
vendored
Normal file
20
thirdparty/sokol/build_clibs_wasm.sh
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
declare -a libs=("log" "gfx" "app" "glue" "time" "audio" "debugtext" "shape" "gl")
|
||||
|
||||
for l in "${libs[@]}"
|
||||
do
|
||||
echo "${l}/sokol_${l}_wasm_gl_debug.a"
|
||||
emcc -c -g -DIMPL -DSOKOL_GLES3 c/sokol_$l.c
|
||||
emar rcs $l/sokol_${l}_wasm_gl_debug.a sokol_$l.o
|
||||
rm sokol_$l.o
|
||||
done
|
||||
|
||||
for l in "${libs[@]}"
|
||||
do
|
||||
echo "${l}/sokol_${l}_wasm_gl_release.a"
|
||||
emcc -c -O2 -DNDEBUG -DIMPL -DSOKOL_GLES3 c/sokol_$l.c
|
||||
emar rcs $l/sokol_${l}_wasm_gl_release.a sokol_$l.o
|
||||
rm sokol_$l.o
|
||||
done
|
45
thirdparty/sokol/build_clibs_windows.cmd
vendored
Normal file
45
thirdparty/sokol/build_clibs_windows.cmd
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
@echo off
|
||||
|
||||
set sources=log app gfx glue time audio debugtext shape gl
|
||||
|
||||
REM D3D11 Debug
|
||||
for %%s in (%sources%) do (
|
||||
cl /c /D_DEBUG /DIMPL /DSOKOL_D3D11 c\sokol_%%s.c /Z7
|
||||
lib /OUT:%%s\sokol_%%s_windows_x64_d3d11_debug.lib sokol_%%s.obj
|
||||
del sokol_%%s.obj
|
||||
)
|
||||
|
||||
REM D3D11 Release
|
||||
for %%s in (%sources%) do (
|
||||
cl /c /O2 /DNDEBUG /DIMPL /DSOKOL_D3D11 c\sokol_%%s.c
|
||||
lib /OUT:%%s\sokol_%%s_windows_x64_d3d11_release.lib sokol_%%s.obj
|
||||
del sokol_%%s.obj
|
||||
)
|
||||
|
||||
REM GL Debug
|
||||
for %%s in (%sources%) do (
|
||||
cl /c /D_DEBUG /DIMPL /DSOKOL_GLCORE c\sokol_%%s.c /Z7
|
||||
lib /OUT:%%s\sokol_%%s_windows_x64_gl_debug.lib sokol_%%s.obj
|
||||
del sokol_%%s.obj
|
||||
)
|
||||
|
||||
REM GL Release
|
||||
for %%s in (%sources%) do (
|
||||
cl /c /O2 /DNDEBUG /DIMPL /DSOKOL_GLCORE c\sokol_%%s.c
|
||||
lib /OUT:%%s\sokol_%%s_windows_x64_gl_release.lib sokol_%%s.obj
|
||||
del sokol_%%s.obj
|
||||
)
|
||||
|
||||
REM D3D11 Debug DLL
|
||||
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_D3D11 c\sokol.c /Z7 /LDd /MDd /DLL /Fe:sokol_dll_windows_x64_d3d11_debug.dll /link /INCREMENTAL:NO
|
||||
|
||||
REM D3D11 Release DLL
|
||||
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_D3D11 c\sokol.c /LD /MD /DLL /Fe:sokol_dll_windows_x64_d3d11_release.dll /link /INCREMENTAL:NO
|
||||
|
||||
REM GL Debug DLL
|
||||
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_GLCORE c\sokol.c /Z7 /LDd /MDd /DLL /Fe:sokol_dll_windows_x64_gl_debug.dll /link /INCREMENTAL:NO
|
||||
|
||||
REM GL Release DLL
|
||||
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_GLCORE c\sokol.c /LD /MD /DLL /Fe:sokol_dll_windows_x64_gl_release.dll /link /INCREMENTAL:NO
|
||||
|
||||
del sokol.obj
|
30
thirdparty/sokol/build_shaders_macos.sh
vendored
Normal file
30
thirdparty/sokol/build_shaders_macos.sh
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
set -e
|
||||
|
||||
sokol_tools_root=../sokol-tools-bin
|
||||
|
||||
build_shader() {
|
||||
name=$1
|
||||
dir=examples/$name
|
||||
if [[ $(arch) =~ "arm64" ]]
|
||||
then
|
||||
shdc=$sokol_tools_root/bin/osx_arm64/sokol-shdc
|
||||
else
|
||||
shdc=$sokol_tools_root/bin/osx/sokol-shdc
|
||||
fi
|
||||
echo $dir
|
||||
$shdc -i $dir/shader.glsl -o $dir/shader.odin -l glsl430:metal_macos:hlsl5 -f sokol_odin
|
||||
}
|
||||
|
||||
build_shader blend
|
||||
build_shader bufferoffsets
|
||||
build_shader cube
|
||||
build_shader instancing
|
||||
build_shader instancing-compute
|
||||
build_shader mrt
|
||||
build_shader noninterleaved
|
||||
build_shader offscreen
|
||||
build_shader quad
|
||||
build_shader shapes
|
||||
build_shader texcube
|
||||
build_shader triangle
|
||||
build_shader vertexpull
|
16
thirdparty/sokol/c/sokol.c
vendored
Normal file
16
thirdparty/sokol/c/sokol.c
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_IMPL
|
||||
#endif
|
||||
|
||||
#include "sokol_defines.h"
|
||||
|
||||
#include "sokol_audio.h"
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_log.h"
|
||||
#include "sokol_time.h"
|
||||
#include "sokol_glue.h"
|
||||
|
||||
#include "sokol_gl.h"
|
||||
#include "sokol_shape.h"
|
||||
#include "sokol_debugtext.h"
|
5
thirdparty/sokol/c/sokol_app.c
vendored
Normal file
5
thirdparty/sokol/c/sokol_app.c
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_APP_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_app.h"
|
12437
thirdparty/sokol/c/sokol_app.h
vendored
Normal file
12437
thirdparty/sokol/c/sokol_app.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
thirdparty/sokol/c/sokol_audio.c
vendored
Normal file
6
thirdparty/sokol/c/sokol_audio.c
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_AUDIO_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_audio.h"
|
||||
|
2310
thirdparty/sokol/c/sokol_audio.h
vendored
Normal file
2310
thirdparty/sokol/c/sokol_audio.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
thirdparty/sokol/c/sokol_debugtext.c
vendored
Normal file
7
thirdparty/sokol/c/sokol_debugtext.c
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_DEBUGTEXT_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_debugtext.h"
|
||||
|
4989
thirdparty/sokol/c/sokol_debugtext.h
vendored
Normal file
4989
thirdparty/sokol/c/sokol_debugtext.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
thirdparty/sokol/c/sokol_defines.h
vendored
Normal file
8
thirdparty/sokol/c/sokol_defines.h
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#define SOKOL_NO_ENTRY
|
||||
#if defined(_WIN32)
|
||||
#define SOKOL_WIN32_FORCE_MAIN
|
||||
#endif
|
||||
// FIXME: macOS Zig HACK without this, some C stdlib headers throw errors
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
5
thirdparty/sokol/c/sokol_gfx.c
vendored
Normal file
5
thirdparty/sokol/c/sokol_gfx.c
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_GFX_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_gfx.h"
|
21518
thirdparty/sokol/c/sokol_gfx.h
vendored
Normal file
21518
thirdparty/sokol/c/sokol_gfx.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
thirdparty/sokol/c/sokol_gl.c
vendored
Normal file
6
thirdparty/sokol/c/sokol_gl.c
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_GL_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_gl.h"
|
4811
thirdparty/sokol/c/sokol_gl.h
vendored
Normal file
4811
thirdparty/sokol/c/sokol_gl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
thirdparty/sokol/c/sokol_glue.c
vendored
Normal file
7
thirdparty/sokol/c/sokol_glue.c
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_GLUE_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_app.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_glue.h"
|
162
thirdparty/sokol/c/sokol_glue.h
vendored
Normal file
162
thirdparty/sokol/c/sokol_glue.h
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
#if defined(SOKOL_IMPL) && !defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_INCLUDED
|
||||
/*
|
||||
sokol_glue.h -- glue helper functions for sokol headers
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_GLUE_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
...optionally provide the following macros to override defaults:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_glue.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
sokol_glue.h provides glue helper functions between sokol_gfx.h and sokol_app.h,
|
||||
so that sokol_gfx.h doesn't need to depend on sokol_app.h but can be
|
||||
used with different window system glue libraries.
|
||||
|
||||
PROVIDED FUNCTIONS
|
||||
==================
|
||||
|
||||
sg_environment sglue_environment(void)
|
||||
|
||||
Returns an sg_environment struct initialized by calling sokol_app.h
|
||||
functions. Use this in the sg_setup() call like this:
|
||||
|
||||
sg_setup(&(sg_desc){
|
||||
.environment = sglue_environment(),
|
||||
...
|
||||
});
|
||||
|
||||
sg_swapchain sglue_swapchain(void)
|
||||
|
||||
Returns an sg_swapchain struct initialized by calling sokol_app.h
|
||||
functions. Use this in sg_begin_pass() for a 'swapchain pass' like
|
||||
this:
|
||||
|
||||
sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain(), ... });
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_GLUE_INCLUDED
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_GLUE_API_DECL)
|
||||
#define SOKOL_GLUE_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_GLUE_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_GFX_INCLUDED
|
||||
#error "Please include sokol_gfx.h before sokol_glue.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_GLUE_API_DECL sg_environment sglue_environment(void);
|
||||
SOKOL_GLUE_API_DECL sg_swapchain sglue_swapchain(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* SOKOL_GLUE_INCLUDED */
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_GLUE_IMPL
|
||||
#define SOKOL_GLUE_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_APP_INCLUDED
|
||||
#error "Please include sokol_app.h before the sokol_glue.h implementation"
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
|
||||
|
||||
SOKOL_API_IMPL sg_environment sglue_environment(void) {
|
||||
sg_environment env;
|
||||
memset(&env, 0, sizeof(env));
|
||||
env.defaults.color_format = (sg_pixel_format) sapp_color_format();
|
||||
env.defaults.depth_format = (sg_pixel_format) sapp_depth_format();
|
||||
env.defaults.sample_count = sapp_sample_count();
|
||||
env.metal.device = sapp_metal_get_device();
|
||||
env.d3d11.device = sapp_d3d11_get_device();
|
||||
env.d3d11.device_context = sapp_d3d11_get_device_context();
|
||||
env.wgpu.device = sapp_wgpu_get_device();
|
||||
return env;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL sg_swapchain sglue_swapchain(void) {
|
||||
sg_swapchain swapchain;
|
||||
memset(&swapchain, 0, sizeof(swapchain));
|
||||
swapchain.width = sapp_width();
|
||||
swapchain.height = sapp_height();
|
||||
swapchain.sample_count = sapp_sample_count();
|
||||
swapchain.color_format = (sg_pixel_format)sapp_color_format();
|
||||
swapchain.depth_format = (sg_pixel_format)sapp_depth_format();
|
||||
swapchain.metal.current_drawable = sapp_metal_get_current_drawable();
|
||||
swapchain.metal.depth_stencil_texture = sapp_metal_get_depth_stencil_texture();
|
||||
swapchain.metal.msaa_color_texture = sapp_metal_get_msaa_color_texture();
|
||||
swapchain.d3d11.render_view = sapp_d3d11_get_render_view();
|
||||
swapchain.d3d11.resolve_view = sapp_d3d11_get_resolve_view();
|
||||
swapchain.d3d11.depth_stencil_view = sapp_d3d11_get_depth_stencil_view();
|
||||
swapchain.wgpu.render_view = sapp_wgpu_get_render_view();
|
||||
swapchain.wgpu.resolve_view = sapp_wgpu_get_resolve_view();
|
||||
swapchain.wgpu.depth_stencil_view = sapp_wgpu_get_depth_stencil_view();
|
||||
swapchain.gl.framebuffer = sapp_gl_get_framebuffer();
|
||||
return swapchain;
|
||||
}
|
||||
|
||||
#endif /* SOKOL_GLUE_IMPL */
|
5
thirdparty/sokol/c/sokol_log.c
vendored
Normal file
5
thirdparty/sokol/c/sokol_log.c
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_LOG_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_log.h"
|
334
thirdparty/sokol/c/sokol_log.h
vendored
Normal file
334
thirdparty/sokol/c/sokol_log.h
vendored
Normal file
@@ -0,0 +1,334 @@
|
||||
#if defined(SOKOL_IMPL) && !defined(SOKOL_LOG_IMPL)
|
||||
#define SOKOL_LOG_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_LOG_INCLUDED
|
||||
/*
|
||||
sokol_log.h -- common logging callback for sokol headers
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Example code: https://github.com/floooh/sokol-samples
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_LOG_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines when building the implementation:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
|
||||
SOKOL_LOG_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
Optionally define the following for verbose output:
|
||||
|
||||
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
|
||||
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
sokol_log.h provides a default logging callback for other sokol headers.
|
||||
|
||||
To use the default log callback, just include sokol_log.h and provide
|
||||
a function pointer to the 'slog_func' function when setting up the
|
||||
sokol library:
|
||||
|
||||
For instance with sokol_audio.h:
|
||||
|
||||
#include "sokol_log.h"
|
||||
...
|
||||
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
|
||||
|
||||
Logging output goes to stderr and/or a platform specific logging subsystem
|
||||
(which means that in some scenarios you might see logging messages duplicated):
|
||||
|
||||
- Windows: stderr + OutputDebugStringA()
|
||||
- macOS/iOS/Linux: stderr + syslog()
|
||||
- Emscripten: console.info()/warn()/error()
|
||||
- Android: __android_log_write()
|
||||
|
||||
On Windows with sokol_app.h also note the runtime config items to make
|
||||
stdout/stderr output visible on the console for WinMain() applications
|
||||
via sapp_desc.win32_console_attach or sapp_desc.win32_console_create,
|
||||
however when running in a debugger on Windows, the logging output should
|
||||
show up on the debug output UI panel.
|
||||
|
||||
In debug mode, a log message might look like this:
|
||||
|
||||
[sspine][error][id:12] /Users/floh/projects/sokol/util/sokol_spine.h:3472:0:
|
||||
SKELETON_DESC_NO_ATLAS: no atlas object provided in sspine_skeleton_desc.atlas
|
||||
|
||||
The source path and line number is formatted like compiler errors, in some IDEs (like VSCode)
|
||||
such error messages are clickable.
|
||||
|
||||
In release mode, logging is less verbose as to not bloat the executable with string data, but you still get
|
||||
enough information to identify the type and location of an error:
|
||||
|
||||
[sspine][error][id:12][line:3472]
|
||||
|
||||
RULES FOR WRITING YOUR OWN LOGGING FUNCTION
|
||||
===========================================
|
||||
- must be re-entrant because it might be called from different threads
|
||||
- must treat **all** provided string pointers as optional (can be null)
|
||||
- don't store the string pointers, copy the string data instead
|
||||
- must not return for log level panic
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2023 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_LOG_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_LOG_API_DECL)
|
||||
#define SOKOL_LOG_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_LOG_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_LOG_IMPL)
|
||||
#define SOKOL_LOG_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_LOG_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_LOG_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
Plug this function into the 'logger.func' struct item when initializing any of the sokol
|
||||
headers. For instance for sokol_audio.h it would look like this:
|
||||
|
||||
saudio_setup(&(saudio_desc){
|
||||
.logger = {
|
||||
.func = slog_func
|
||||
}
|
||||
});
|
||||
*/
|
||||
SOKOL_LOG_API_DECL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // SOKOL_LOG_INCLUDED
|
||||
|
||||
// ██ ███ ███ ██████ ██ ███████ ███ ███ ███████ ███ ██ ████████ █████ ████████ ██ ██████ ███ ██
|
||||
// ██ ████ ████ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
|
||||
// ██ ██ ████ ██ ██████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██
|
||||
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
// ██ ██ ██ ██ ███████ ███████ ██ ██ ███████ ██ ████ ██ ██ ██ ██ ██ ██████ ██ ████
|
||||
//
|
||||
// >>implementation
|
||||
#ifdef SOKOL_LOG_IMPL
|
||||
#define SOKOL_LOG_IMPL_INCLUDED (1)
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define SOKOL_DEBUG
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _SOKOL_UNUSED
|
||||
#define _SOKOL_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
// platform detection
|
||||
#if defined(__APPLE__)
|
||||
#define _SLOG_APPLE (1)
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define _SLOG_EMSCRIPTEN (1)
|
||||
#elif defined(_WIN32)
|
||||
#define _SLOG_WINDOWS (1)
|
||||
#elif defined(__ANDROID__)
|
||||
#define _SLOG_ANDROID (1)
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
#define _SLOG_LINUX (1)
|
||||
#else
|
||||
#error "sokol_log.h: unknown platform"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // abort
|
||||
#include <stdio.h> // fputs
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#if defined(_SLOG_EMSCRIPTEN)
|
||||
#include <emscripten/emscripten.h>
|
||||
#elif defined(_SLOG_WINDOWS)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(_SLOG_ANDROID)
|
||||
#include <android/log.h>
|
||||
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
// size of line buffer (on stack!) in bytes including terminating zero
|
||||
#define _SLOG_LINE_LENGTH (512)
|
||||
|
||||
_SOKOL_PRIVATE char* _slog_append(const char* str, char* dst, char* end) {
|
||||
if (str) {
|
||||
char c;
|
||||
while (((c = *str++) != 0) && (dst < (end - 1))) {
|
||||
*dst++ = c;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE char* _slog_itoa(uint32_t x, char* buf, size_t buf_size) {
|
||||
const size_t max_digits_and_null = 11;
|
||||
if (buf_size < max_digits_and_null) {
|
||||
return 0;
|
||||
}
|
||||
char* p = buf + max_digits_and_null;
|
||||
*--p = 0;
|
||||
do {
|
||||
*--p = '0' + (x % 10);
|
||||
x /= 10;
|
||||
} while (x != 0);
|
||||
return p;
|
||||
}
|
||||
|
||||
#if defined(_SLOG_EMSCRIPTEN)
|
||||
EM_JS(void, slog_js_log, (uint32_t level, const char* c_str), {
|
||||
const str = UTF8ToString(c_str);
|
||||
switch (level) {
|
||||
case 0: console.error(str); break;
|
||||
case 1: console.error(str); break;
|
||||
case 2: console.warn(str); break;
|
||||
default: console.info(str); break;
|
||||
}
|
||||
})
|
||||
#endif
|
||||
|
||||
SOKOL_API_IMPL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data) {
|
||||
_SOKOL_UNUSED(user_data);
|
||||
|
||||
const char* log_level_str;
|
||||
switch (log_level) {
|
||||
case 0: log_level_str = "panic"; break;
|
||||
case 1: log_level_str = "error"; break;
|
||||
case 2: log_level_str = "warning"; break;
|
||||
default: log_level_str = "info"; break;
|
||||
}
|
||||
|
||||
// build log output line
|
||||
char line_buf[_SLOG_LINE_LENGTH];
|
||||
char* str = line_buf;
|
||||
char* end = line_buf + sizeof(line_buf);
|
||||
char num_buf[32];
|
||||
if (tag) {
|
||||
str = _slog_append("[", str, end);
|
||||
str = _slog_append(tag, str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
}
|
||||
str = _slog_append("[", str, end);
|
||||
str = _slog_append(log_level_str, str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
str = _slog_append("[id:", str, end);
|
||||
str = _slog_append(_slog_itoa(log_item, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
// if a filename is provided, build a clickable log message that's compatible with compiler error messages
|
||||
if (filename) {
|
||||
str = _slog_append(" ", str, end);
|
||||
#if defined(_MSC_VER)
|
||||
// MSVC compiler error format
|
||||
str = _slog_append(filename, str, end);
|
||||
str = _slog_append("(", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("): ", str, end);
|
||||
#else
|
||||
// gcc/clang compiler error format
|
||||
str = _slog_append(filename, str, end);
|
||||
str = _slog_append(":", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append(":0: ", str, end);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
str = _slog_append("[line:", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("] ", str, end);
|
||||
}
|
||||
if (message) {
|
||||
str = _slog_append("\n\t", str, end);
|
||||
str = _slog_append(message, str, end);
|
||||
}
|
||||
str = _slog_append("\n\n", str, end);
|
||||
if (0 == log_level) {
|
||||
str = _slog_append("ABORTING because of [panic]\n", str, end);
|
||||
(void)str;
|
||||
}
|
||||
|
||||
// print to stderr?
|
||||
#if defined(_SLOG_LINUX) || defined(_SLOG_WINDOWS) || defined(_SLOG_APPLE)
|
||||
fputs(line_buf, stderr);
|
||||
#endif
|
||||
|
||||
// platform specific logging calls
|
||||
#if defined(_SLOG_WINDOWS)
|
||||
OutputDebugStringA(line_buf);
|
||||
#elif defined(_SLOG_ANDROID)
|
||||
int prio;
|
||||
switch (log_level) {
|
||||
case 0: prio = ANDROID_LOG_FATAL; break;
|
||||
case 1: prio = ANDROID_LOG_ERROR; break;
|
||||
case 2: prio = ANDROID_LOG_WARN; break;
|
||||
default: prio = ANDROID_LOG_INFO; break;
|
||||
}
|
||||
__android_log_write(prio, "SOKOL", line_buf);
|
||||
#elif defined(_SLOG_EMSCRIPTEN)
|
||||
slog_js_log(log_level, line_buf);
|
||||
#endif
|
||||
if (0 == log_level) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif // SOKOL_LOG_IMPL
|
6
thirdparty/sokol/c/sokol_shape.c
vendored
Normal file
6
thirdparty/sokol/c/sokol_shape.c
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_SHAPE_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_gfx.h"
|
||||
#include "sokol_shape.h"
|
1431
thirdparty/sokol/c/sokol_shape.h
vendored
Normal file
1431
thirdparty/sokol/c/sokol_shape.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
thirdparty/sokol/c/sokol_time.c
vendored
Normal file
5
thirdparty/sokol/c/sokol_time.c
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#if defined(IMPL)
|
||||
#define SOKOL_TIME_IMPL
|
||||
#endif
|
||||
#include "sokol_defines.h"
|
||||
#include "sokol_time.h"
|
319
thirdparty/sokol/c/sokol_time.h
vendored
Normal file
319
thirdparty/sokol/c/sokol_time.h
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
#if defined(SOKOL_IMPL) && !defined(SOKOL_TIME_IMPL)
|
||||
#define SOKOL_TIME_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_TIME_INCLUDED
|
||||
/*
|
||||
sokol_time.h -- simple cross-platform time measurement
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_TIME_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines with your own implementations:
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_TIME_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_TIME_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_time.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_TIME_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
void stm_setup();
|
||||
Call once before any other functions to initialize sokol_time
|
||||
(this calls for instance QueryPerformanceFrequency on Windows)
|
||||
|
||||
uint64_t stm_now();
|
||||
Get current point in time in unspecified 'ticks'. The value that
|
||||
is returned has no relation to the 'wall-clock' time and is
|
||||
not in a specific time unit, it is only useful to compute
|
||||
time differences.
|
||||
|
||||
uint64_t stm_diff(uint64_t new, uint64_t old);
|
||||
Computes the time difference between new and old. This will always
|
||||
return a positive, non-zero value.
|
||||
|
||||
uint64_t stm_since(uint64_t start);
|
||||
Takes the current time, and returns the elapsed time since start
|
||||
(this is a shortcut for "stm_diff(stm_now(), start)")
|
||||
|
||||
uint64_t stm_laptime(uint64_t* last_time);
|
||||
This is useful for measuring frame time and other recurring
|
||||
events. It takes the current time, returns the time difference
|
||||
to the value in last_time, and stores the current time in
|
||||
last_time for the next call. If the value in last_time is 0,
|
||||
the return value will be zero (this usually happens on the
|
||||
very first call).
|
||||
|
||||
uint64_t stm_round_to_common_refresh_rate(uint64_t duration)
|
||||
This oddly named function takes a measured frame time and
|
||||
returns the closest "nearby" common display refresh rate frame duration
|
||||
in ticks. If the input duration isn't close to any common display
|
||||
refresh rate, the input duration will be returned unchanged as a fallback.
|
||||
The main purpose of this function is to remove jitter/inaccuracies from
|
||||
measured frame times, and instead use the display refresh rate as
|
||||
frame duration.
|
||||
NOTE: for more robust frame timing, consider using the
|
||||
sokol_app.h function sapp_frame_duration()
|
||||
|
||||
Use the following functions to convert a duration in ticks into
|
||||
useful time units:
|
||||
|
||||
double stm_sec(uint64_t ticks);
|
||||
double stm_ms(uint64_t ticks);
|
||||
double stm_us(uint64_t ticks);
|
||||
double stm_ns(uint64_t ticks);
|
||||
Converts a tick value into seconds, milliseconds, microseconds
|
||||
or nanoseconds. Note that not all platforms will have nanosecond
|
||||
or even microsecond precision.
|
||||
|
||||
Uses the following time measurement functions under the hood:
|
||||
|
||||
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
|
||||
MacOS/iOS: mach_absolute_time()
|
||||
emscripten: emscripten_get_now()
|
||||
Linux+others: clock_gettime(CLOCK_MONOTONIC)
|
||||
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_TIME_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_TIME_API_DECL)
|
||||
#define SOKOL_TIME_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_TIME_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_TIME_IMPL)
|
||||
#define SOKOL_TIME_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_TIME_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_TIME_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_TIME_API_DECL void stm_setup(void);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_now(void);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_since(uint64_t start_ticks);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_laptime(uint64_t* last_time);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_round_to_common_refresh_rate(uint64_t frame_ticks);
|
||||
SOKOL_TIME_API_DECL double stm_sec(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_ms(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_us(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_ns(uint64_t ticks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif // SOKOL_TIME_INCLUDED
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_TIME_IMPL
|
||||
#define SOKOL_TIME_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <mach/mach_time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
mach_timebase_info_data_t timebase;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include <emscripten/emscripten.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
double start;
|
||||
} _stm_state_t;
|
||||
#else /* anything else, this will need more care for non-Linux platforms */
|
||||
#ifdef ESP8266
|
||||
// On the ESP8266, clock_gettime ignores the first argument and CLOCK_MONOTONIC isn't defined
|
||||
#define CLOCK_MONOTONIC 0
|
||||
#endif
|
||||
#include <time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#endif
|
||||
static _stm_state_t _stm;
|
||||
|
||||
/* prevent 64-bit overflow when computing relative timestamp
|
||||
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
|
||||
*/
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
|
||||
_SOKOL_PRIVATE int64_t _stm_int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
|
||||
int64_t q = value / denom;
|
||||
int64_t r = value % denom;
|
||||
return q * numer + r * numer / denom;
|
||||
}
|
||||
#endif
|
||||
|
||||
SOKOL_API_IMPL void stm_setup(void) {
|
||||
memset(&_stm, 0, sizeof(_stm));
|
||||
_stm.initialized = 0xABCDABCD;
|
||||
#if defined(_WIN32)
|
||||
QueryPerformanceFrequency(&_stm.freq);
|
||||
QueryPerformanceCounter(&_stm.start);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
mach_timebase_info(&_stm.timebase);
|
||||
_stm.start = mach_absolute_time();
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
_stm.start = emscripten_get_now();
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
_stm.start = (uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_now(void) {
|
||||
SOKOL_ASSERT(_stm.initialized == 0xABCDABCD);
|
||||
uint64_t now;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER qpc_t;
|
||||
QueryPerformanceCounter(&qpc_t);
|
||||
now = (uint64_t) _stm_int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
const uint64_t mach_now = mach_absolute_time() - _stm.start;
|
||||
now = (uint64_t) _stm_int64_muldiv((int64_t)mach_now, (int64_t)_stm.timebase.numer, (int64_t)_stm.timebase.denom);
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
double js_now = emscripten_get_now() - _stm.start;
|
||||
now = (uint64_t) (js_now * 1000000.0);
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ((uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec) - _stm.start;
|
||||
#endif
|
||||
return now;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks) {
|
||||
if (new_ticks > old_ticks) {
|
||||
return new_ticks - old_ticks;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks) {
|
||||
return stm_diff(stm_now(), start_ticks);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
|
||||
SOKOL_ASSERT(last_time);
|
||||
uint64_t dt = 0;
|
||||
uint64_t now = stm_now();
|
||||
if (0 != *last_time) {
|
||||
dt = stm_diff(now, *last_time);
|
||||
}
|
||||
*last_time = now;
|
||||
return dt;
|
||||
}
|
||||
|
||||
// first number is frame duration in ns, second number is tolerance in ns,
|
||||
// the resulting min/max values must not overlap!
|
||||
static const uint64_t _stm_refresh_rates[][2] = {
|
||||
{ 16666667, 1000000 }, // 60 Hz: 16.6667 +- 1ms
|
||||
{ 13888889, 250000 }, // 72 Hz: 13.8889 +- 0.25ms
|
||||
{ 13333333, 250000 }, // 75 Hz: 13.3333 +- 0.25ms
|
||||
{ 11764706, 250000 }, // 85 Hz: 11.7647 +- 0.25
|
||||
{ 11111111, 250000 }, // 90 Hz: 11.1111 +- 0.25ms
|
||||
{ 10000000, 500000 }, // 100 Hz: 10.0000 +- 0.5ms
|
||||
{ 8333333, 500000 }, // 120 Hz: 8.3333 +- 0.5ms
|
||||
{ 6944445, 500000 }, // 144 Hz: 6.9445 +- 0.5ms
|
||||
{ 4166667, 1000000 }, // 240 Hz: 4.1666 +- 1ms
|
||||
{ 0, 0 }, // keep the last element always at zero
|
||||
};
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_round_to_common_refresh_rate(uint64_t ticks) {
|
||||
uint64_t ns;
|
||||
int i = 0;
|
||||
while (0 != (ns = _stm_refresh_rates[i][0])) {
|
||||
uint64_t tol = _stm_refresh_rates[i][1];
|
||||
if ((ticks > (ns - tol)) && (ticks < (ns + tol))) {
|
||||
return ns;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// fallthrough: didn't fit into any buckets
|
||||
return ticks;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_sec(uint64_t ticks) {
|
||||
return (double)ticks / 1000000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ms(uint64_t ticks) {
|
||||
return (double)ticks / 1000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_us(uint64_t ticks) {
|
||||
return (double)ticks / 1000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ns(uint64_t ticks) {
|
||||
return (double)ticks;
|
||||
}
|
||||
#endif /* SOKOL_TIME_IMPL */
|
||||
|
740
thirdparty/sokol/debugtext/debugtext.odin
vendored
Normal file
740
thirdparty/sokol/debugtext/debugtext.odin
vendored
Normal file
@@ -0,0 +1,740 @@
|
||||
// machine generated, do not edit
|
||||
|
||||
package sokol_debugtext
|
||||
|
||||
/*
|
||||
|
||||
sokol_debugtext.h - simple ASCII debug text rendering on top of sokol_gfx.h
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_DEBUGTEXT_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
The following defines are used by the implementation to select the
|
||||
platform-specific embedded shader code (these are the same defines as
|
||||
used by sokol_gfx.h and sokol_app.h):
|
||||
|
||||
SOKOL_GLCORE
|
||||
SOKOL_GLES3
|
||||
SOKOL_D3D11
|
||||
SOKOL_METAL
|
||||
SOKOL_WGPU
|
||||
|
||||
...optionally provide the following macros to override defaults:
|
||||
|
||||
SOKOL_VSNPRINTF - the function name of an alternative vsnprintf() function (default: vsnprintf)
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_DEBUGTEXT_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_DEBUGTEXT_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
|
||||
|
||||
If sokol_debugtext.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_DEBUGTEXT_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
Include the following headers before including sokol_debugtext.h:
|
||||
|
||||
sokol_gfx.h
|
||||
|
||||
FEATURES AND CONCEPTS
|
||||
=====================
|
||||
- renders 8-bit ASCII text as fixed-size 8x8 pixel characters
|
||||
- comes with 6 embedded 8-bit home computer fonts (each taking up 2 KBytes)
|
||||
- easily plug in your own fonts
|
||||
- create multiple contexts for rendering text in different layers or render passes
|
||||
|
||||
STEP BY STEP
|
||||
============
|
||||
|
||||
--- to initialize sokol-debugtext, call sdtx_setup() *after* initializing
|
||||
sokol-gfx:
|
||||
|
||||
sdtx_setup(&(sdtx_desc_t){ ... });
|
||||
|
||||
To see any warnings and errors, you should always install a logging callback.
|
||||
The easiest way is via sokol_log.h:
|
||||
|
||||
#include "sokol_log.h"
|
||||
|
||||
sdtx_setup(&(sdtx_desc_t){
|
||||
.logger.func = slog_func,
|
||||
});
|
||||
|
||||
--- configure sokol-debugtext by populating the sdtx_desc_t struct:
|
||||
|
||||
.context_pool_size (default: 8)
|
||||
The max number of text contexts that can be created.
|
||||
|
||||
.printf_buf_size (default: 4096)
|
||||
The size of the internal text formatting buffer used by
|
||||
sdtx_printf() and sdtx_vprintf().
|
||||
|
||||
.fonts (default: none)
|
||||
An array of sdtx_font_desc_t structs used to configure the
|
||||
fonts that can be used for rendering. To use all builtin
|
||||
fonts call sdtx_setup() like this (in C99):
|
||||
|
||||
sdtx_setup(&(sdtx_desc_t){
|
||||
.fonts = {
|
||||
[0] = sdtx_font_kc853(),
|
||||
[1] = sdtx_font_kc854(),
|
||||
[2] = sdtx_font_z1013(),
|
||||
[3] = sdtx_font_cpc(),
|
||||
[4] = sdtx_font_c64(),
|
||||
[5] = sdtx_font_oric()
|
||||
}
|
||||
});
|
||||
|
||||
For documentation on how to use you own font data, search
|
||||
below for "USING YOUR OWN FONT DATA".
|
||||
|
||||
.context
|
||||
The setup parameters for the default text context. This will
|
||||
be active right after sdtx_setup(), or when calling
|
||||
sdtx_set_context(SDTX_DEFAULT_CONTEXT):
|
||||
|
||||
.max_commands (default: 4096)
|
||||
The max number of render commands that can be recorded
|
||||
into the internal command buffer. This directly translates
|
||||
to the number of render layer changes in a single frame.
|
||||
|
||||
.char_buf_size (default: 4096)
|
||||
The number of characters that can be rendered per frame in this
|
||||
context, defines the size of an internal fixed-size vertex
|
||||
buffer. Any additional characters will be silently ignored.
|
||||
|
||||
.canvas_width (default: 640)
|
||||
.canvas_height (default: 480)
|
||||
The 'virtual canvas size' in pixels. This defines how big
|
||||
characters will be rendered relative to the default framebuffer
|
||||
dimensions. Each character occupies a grid of 8x8 'virtual canvas
|
||||
pixels' (so a virtual canvas size of 640x480 means that 80x60 characters
|
||||
fit on the screen). For rendering in a resizeable window, you
|
||||
should dynamically update the canvas size in each frame by
|
||||
calling sdtx_canvas(w, h).
|
||||
|
||||
.tab_width (default: 4)
|
||||
The width of a tab character in number of character cells.
|
||||
|
||||
.color_format (default: 0)
|
||||
.depth_format (default: 0)
|
||||
.sample_count (default: 0)
|
||||
The pixel format description for the default context needed
|
||||
for creating the context's sg_pipeline object. When
|
||||
rendering to the default framebuffer you can leave those
|
||||
zero-initialized, in this case the proper values will be
|
||||
filled in by sokol-gfx. You only need to provide non-default
|
||||
values here when rendering to render targets with different
|
||||
pixel format attributes than the default framebuffer.
|
||||
|
||||
--- Before starting to render text, optionally call sdtx_canvas() to
|
||||
dynamically resize the virtual canvas. This is recommended when
|
||||
rendering to a resizeable window. The virtual canvas size can
|
||||
also be used to scale text in relation to the display resolution.
|
||||
|
||||
Examples when using sokol-app:
|
||||
|
||||
- to render characters at 8x8 'physical pixels':
|
||||
|
||||
sdtx_canvas(sapp_width(), sapp_height());
|
||||
|
||||
- to render characters at 16x16 physical pixels:
|
||||
|
||||
sdtx_canvas(sapp_width()/2.0f, sapp_height()/2.0f);
|
||||
|
||||
Do *not* use integer math here, since this will not look nice
|
||||
when the render target size isn't divisible by 2.
|
||||
|
||||
--- Optionally define the origin for the character grid with:
|
||||
|
||||
sdtx_origin(x, y);
|
||||
|
||||
The provided coordinates are in character grid cells, not in
|
||||
virtual canvas pixels. E.g. to set the origin to 2 character tiles
|
||||
from the left and top border:
|
||||
|
||||
sdtx_origin(2, 2);
|
||||
|
||||
You can define fractions, e.g. to start rendering half
|
||||
a character tile from the top-left corner:
|
||||
|
||||
sdtx_origin(0.5f, 0.5f);
|
||||
|
||||
--- Optionally set a different font by calling:
|
||||
|
||||
sdtx_font(font_index)
|
||||
|
||||
sokol-debugtext provides 8 font slots which can be populated
|
||||
with the builtin fonts or with user-provided font data, so
|
||||
'font_index' must be a number from 0 to 7.
|
||||
|
||||
--- Position the text cursor with one of the following calls. All arguments
|
||||
are in character grid cells as floats and relative to the
|
||||
origin defined with sdtx_origin():
|
||||
|
||||
sdtx_pos(x, y) - sets absolute cursor position
|
||||
sdtx_pos_x(x) - only set absolute x cursor position
|
||||
sdtx_pos_y(y) - only set absolute y cursor position
|
||||
|
||||
sdtx_move(x, y) - move cursor relative in x and y direction
|
||||
sdtx_move_x(x) - move cursor relative only in x direction
|
||||
sdtx_move_y(y) - move cursor relative only in y direction
|
||||
|
||||
sdtx_crlf() - set cursor to beginning of next line
|
||||
(same as sdtx_pos_x(0) + sdtx_move_y(1))
|
||||
sdtx_home() - resets the cursor to the origin
|
||||
(same as sdtx_pos(0, 0))
|
||||
|
||||
--- Set a new text color with any of the following functions:
|
||||
|
||||
sdtx_color3b(r, g, b) - RGB 0..255, A=255
|
||||
sdtx_color3f(r, g, b) - RGB 0.0f..1.0f, A=1.0f
|
||||
sdtx_color4b(r, g, b, a) - RGBA 0..255
|
||||
sdtx_color4f(r, g, b, a) - RGBA 0.0f..1.0f
|
||||
sdtx_color1i(uint32_t rgba) - ABGR (0xAABBGGRR)
|
||||
|
||||
--- Output 8-bit ASCII text with the following functions:
|
||||
|
||||
sdtx_putc(c) - output a single character
|
||||
|
||||
sdtx_puts(str) - output a null-terminated C string, note that
|
||||
this will *not* append a newline (so it behaves
|
||||
differently than the CRT's puts() function)
|
||||
|
||||
sdtx_putr(str, len) - 'put range' output the first 'len' characters of
|
||||
a C string or until the zero character is encountered
|
||||
|
||||
sdtx_printf(fmt, ...) - output with printf-formatting, note that you
|
||||
can inject your own printf-compatible function
|
||||
by overriding the SOKOL_VSNPRINTF define before
|
||||
including the implementation
|
||||
|
||||
sdtx_vprintf(fmt, args) - same as sdtx_printf() but with the arguments
|
||||
provided in a va_list
|
||||
|
||||
- Note that the text will not yet be rendered, only recorded for rendering
|
||||
at a later time, the actual rendering happens when sdtx_draw() is called
|
||||
inside a sokol-gfx render pass.
|
||||
- This means also you can output text anywhere in the frame, it doesn't
|
||||
have to be inside a render pass.
|
||||
- Note that character codes <32 are reserved as control characters
|
||||
and won't render anything. Currently only the following control
|
||||
characters are implemented:
|
||||
|
||||
\r - carriage return (same as sdtx_pos_x(0))
|
||||
\n - carriage return + line feed (same as stdx_crlf())
|
||||
\t - a tab character
|
||||
|
||||
--- You can 'record' text into render layers, this allows to mix/interleave
|
||||
sokol-debugtext rendering with other rendering operations inside
|
||||
sokol-gfx render passes. To start recording text into a different render
|
||||
layer, call:
|
||||
|
||||
sdtx_layer(int layer_id)
|
||||
|
||||
...outside a sokol-gfx render pass.
|
||||
|
||||
--- finally, from within a sokol-gfx render pass, call:
|
||||
|
||||
sdtx_draw()
|
||||
|
||||
...for non-layered rendering, or to draw a specific layer:
|
||||
|
||||
sdtx_draw_layer(int layer_id)
|
||||
|
||||
NOTE that sdtx_draw() is equivalent to:
|
||||
|
||||
sdtx_draw_layer(0)
|
||||
|
||||
...so sdtx_draw() will *NOT* render all text layers, instead it will
|
||||
only render the 'default layer' 0.
|
||||
|
||||
--- at the end of a frame (defined by the call to sg_commit()), sokol-debugtext
|
||||
will rewind all contexts:
|
||||
|
||||
- the internal vertex index is set to 0
|
||||
- the internal command index is set to 0
|
||||
- the current layer id is set to 0
|
||||
- the current font is set to 0
|
||||
- the cursor position is reset
|
||||
|
||||
|
||||
RENDERING WITH MULTIPLE CONTEXTS
|
||||
================================
|
||||
Use multiple text contexts if you need to render debug text in different
|
||||
sokol-gfx render passes, or want to render text to different layers
|
||||
in the same render pass, each with its own set of parameters.
|
||||
|
||||
To create a new text context call:
|
||||
|
||||
sdtx_context ctx = sdtx_make_context(&(sdtx_context_desc_t){ ... });
|
||||
|
||||
The creation parameters in the sdtx_context_desc_t struct are the same
|
||||
as already described above in the sdtx_setup() function:
|
||||
|
||||
.char_buf_size -- max number of characters rendered in one frame, default: 4096
|
||||
.canvas_width -- the initial virtual canvas width, default: 640
|
||||
.canvas_height -- the initial virtual canvas height, default: 400
|
||||
.tab_width -- tab width in number of characters, default: 4
|
||||
.color_format -- color pixel format of target render pass
|
||||
.depth_format -- depth pixel format of target render pass
|
||||
.sample_count -- MSAA sample count of target render pass
|
||||
|
||||
To make a new context the active context, call:
|
||||
|
||||
sdtx_set_context(ctx)
|
||||
|
||||
...and after that call the text output functions as described above, and
|
||||
finally, inside a sokol-gfx render pass, call sdtx_draw() to actually
|
||||
render the text for this context.
|
||||
|
||||
A context keeps track of the following parameters:
|
||||
|
||||
- the active font
|
||||
- the virtual canvas size
|
||||
- the origin position
|
||||
- the current cursor position
|
||||
- the current tab width
|
||||
- the current color
|
||||
- and the current layer-id
|
||||
|
||||
You can get the currently active context with:
|
||||
|
||||
sdtx_get_context()
|
||||
|
||||
To make the default context current, call sdtx_set_context() with the
|
||||
special SDTX_DEFAULT_CONTEXT handle:
|
||||
|
||||
sdtx_set_context(SDTX_DEFAULT_CONTEXT)
|
||||
|
||||
Alternatively, use the function sdtx_default_context() to get the default
|
||||
context handle:
|
||||
|
||||
sdtx_set_context(sdtx_default_context());
|
||||
|
||||
To destroy a context, call:
|
||||
|
||||
sdtx_destroy_context(ctx)
|
||||
|
||||
If a context is set as active that no longer exists, all sokol-debugtext
|
||||
functions that require an active context will silently fail.
|
||||
|
||||
You can directly draw the recorded text in a specific context without
|
||||
setting the active context:
|
||||
|
||||
sdtx_context_draw(ctx)
|
||||
sdtx_context_draw_layer(ctx, layer_id)
|
||||
|
||||
USING YOUR OWN FONT DATA
|
||||
========================
|
||||
|
||||
Instead of the built-in fonts you can also plug your own font data
|
||||
into sokol-debugtext by providing one or several sdtx_font_desc_t
|
||||
structures in the sdtx_setup call.
|
||||
|
||||
For instance to use a built-in font at slot 0, and a user-font at
|
||||
font slot 1, the sdtx_setup() call might look like this:
|
||||
|
||||
sdtx_setup(&sdtx_desc_t){
|
||||
.fonts = {
|
||||
[0] = sdtx_font_kc853(),
|
||||
[1] = {
|
||||
.data = {
|
||||
.ptr = my_font_data,
|
||||
.size = sizeof(my_font_data)
|
||||
},
|
||||
.first_char = ...,
|
||||
.last_char = ...
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Where 'my_font_data' is a byte array where every character is described
|
||||
by 8 bytes arranged like this:
|
||||
|
||||
bits
|
||||
7 6 5 4 3 2 1 0
|
||||
. . . X X . . . byte 0: 0x18
|
||||
. . X X X X . . byte 1: 0x3C
|
||||
. X X . . X X . byte 2: 0x66
|
||||
. X X . . X X . byte 3: 0x66
|
||||
. X X X X X X . byte 4: 0x7E
|
||||
. X X . . X X . byte 5: 0x66
|
||||
. X X . . X X . byte 6: 0x66
|
||||
. . . . . . . . byte 7: 0x00
|
||||
|
||||
A complete font consists of 256 characters, resulting in 2048 bytes for
|
||||
the font data array (but note that the character codes 0..31 will never
|
||||
be rendered).
|
||||
|
||||
If you provide such a complete font data array, you can drop the .first_char
|
||||
and .last_char initialization parameters since those default to 0 and 255,
|
||||
note that you can also use the SDTX_RANGE() helper macro to build the
|
||||
.data item:
|
||||
|
||||
sdtx_setup(&sdtx_desc_t){
|
||||
.fonts = {
|
||||
[0] = sdtx_font_kc853(),
|
||||
[1] = {
|
||||
.data = SDTX_RANGE(my_font_data)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
If the font doesn't define all 256 character tiles, or you don't need an
|
||||
entire 256-character font and want to save a couple of bytes, use the
|
||||
.first_char and .last_char initialization parameters to define a sub-range.
|
||||
For instance if the font only contains the characters between the Space
|
||||
(ASCII code 32) and uppercase character 'Z' (ASCII code 90):
|
||||
|
||||
sdtx_setup(&sdtx_desc_t){
|
||||
.fonts = {
|
||||
[0] = sdtx_font_kc853(),
|
||||
[1] = {
|
||||
.data = SDTX_RANGE(my_font_data),
|
||||
.first_char = 32, // could also write ' '
|
||||
.last_char = 90 // could also write 'Z'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Character tiles that haven't been defined in the font will be rendered
|
||||
as a solid 8x8 quad.
|
||||
|
||||
|
||||
MEMORY ALLOCATION OVERRIDE
|
||||
==========================
|
||||
You can override the memory allocation functions at initialization time
|
||||
like this:
|
||||
|
||||
void* my_alloc(size_t size, void* user_data) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void my_free(void* ptr, void* user_data) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
...
|
||||
sdtx_setup(&(sdtx_desc_t){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...;
|
||||
}
|
||||
});
|
||||
...
|
||||
|
||||
If no overrides are provided, malloc and free will be used.
|
||||
|
||||
|
||||
ERROR REPORTING AND LOGGING
|
||||
===========================
|
||||
To get any logging information at all you need to provide a logging callback in the setup call,
|
||||
the easiest way is to use sokol_log.h:
|
||||
|
||||
#include "sokol_log.h"
|
||||
|
||||
sdtx_setup(&(sdtx_desc_t){
|
||||
// ...
|
||||
.logger.func = slog_func
|
||||
});
|
||||
|
||||
To override logging with your own callback, first write a logging function like this:
|
||||
|
||||
void my_log(const char* tag, // e.g. 'sdtx'
|
||||
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
|
||||
uint32_t log_item_id, // SDTX_LOGITEM_*
|
||||
const char* message_or_null, // a message string, may be nullptr in release mode
|
||||
uint32_t line_nr, // line number in sokol_debugtext.h
|
||||
const char* filename_or_null, // source filename, may be nullptr in release mode
|
||||
void* user_data)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
...and then setup sokol-debugtext like this:
|
||||
|
||||
sdtx_setup(&(sdtx_desc_t){
|
||||
.logger = {
|
||||
.func = my_log,
|
||||
.user_data = my_user_data,
|
||||
}
|
||||
});
|
||||
|
||||
The provided logging function must be reentrant (e.g. be callable from
|
||||
different threads).
|
||||
|
||||
If you don't want to provide your own custom logger it is highly recommended to use
|
||||
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
|
||||
errors.
|
||||
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2020 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
*/
|
||||
import sg "../gfx"
|
||||
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
printf :: proc(s: string, args: ..any) {
|
||||
fstr := fmt.tprintf(s, ..args)
|
||||
putr(strings.unsafe_string_to_cstring(fstr), len(fstr))
|
||||
}
|
||||
import "core:c"
|
||||
|
||||
_ :: c
|
||||
|
||||
SOKOL_DEBUG :: #config(SOKOL_DEBUG, ODIN_DEBUG)
|
||||
|
||||
DEBUG :: #config(SOKOL_DEBUGTEXT_DEBUG, SOKOL_DEBUG)
|
||||
USE_GL :: #config(SOKOL_USE_GL, false)
|
||||
USE_DLL :: #config(SOKOL_DLL, false)
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
when USE_DLL {
|
||||
when USE_GL {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "../sokol_dll_windows_x64_gl_debug.lib" } }
|
||||
else { foreign import sokol_debugtext_clib { "../sokol_dll_windows_x64_gl_release.lib" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "../sokol_dll_windows_x64_d3d11_debug.lib" } }
|
||||
else { foreign import sokol_debugtext_clib { "../sokol_dll_windows_x64_d3d11_release.lib" } }
|
||||
}
|
||||
} else {
|
||||
when USE_GL {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_windows_x64_gl_debug.lib" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_windows_x64_gl_release.lib" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_windows_x64_d3d11_debug.lib" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_windows_x64_d3d11_release.lib" } }
|
||||
}
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
when USE_DLL {
|
||||
when USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_arm64_gl_release.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_x64_gl_debug.dylib" } }
|
||||
else when USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_x64_gl_release.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .arm64 && DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .arm64 && !DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_arm64_metal_release.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .amd64 && DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_x64_metal_debug.dylib" } }
|
||||
else when !USE_GL && ODIN_ARCH == .amd64 && !DEBUG { foreign import sokol_debugtext_clib { "../dylib/sokol_dylib_macos_x64_metal_release.dylib" } }
|
||||
} else {
|
||||
when USE_GL {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_arm64_gl_debug.a" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_arm64_gl_release.a" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_x64_gl_debug.a" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_x64_gl_release.a" } }
|
||||
}
|
||||
} else {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_arm64_metal_debug.a" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_arm64_metal_release.a" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_x64_metal_debug.a" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_macos_x64_metal_release.a" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else when ODIN_OS == .Linux {
|
||||
when USE_DLL {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_linux_x64_gl_debug.so" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_linux_x64_gl_release.so" } }
|
||||
} else {
|
||||
when DEBUG { foreign import sokol_debugtext_clib { "sokol_debugtext_linux_x64_gl_debug.a" } }
|
||||
else { foreign import sokol_debugtext_clib { "sokol_debugtext_linux_x64_gl_release.a" } }
|
||||
}
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
// Feed sokol_debugtext_wasm_gl_debug.a or sokol_debugtext_wasm_gl_release.a into emscripten compiler.
|
||||
foreign import sokol_debugtext_clib { "env.o" }
|
||||
} else {
|
||||
#panic("This OS is currently not supported")
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="sdtx_")
|
||||
foreign sokol_debugtext_clib {
|
||||
// initialization/shutdown
|
||||
setup :: proc(#by_ptr desc: Desc) ---
|
||||
shutdown :: proc() ---
|
||||
// builtin font data (use to populate sdtx_desc.font[])
|
||||
font_kc853 :: proc() -> Font_Desc ---
|
||||
font_kc854 :: proc() -> Font_Desc ---
|
||||
font_z1013 :: proc() -> Font_Desc ---
|
||||
font_cpc :: proc() -> Font_Desc ---
|
||||
font_c64 :: proc() -> Font_Desc ---
|
||||
font_oric :: proc() -> Font_Desc ---
|
||||
// context functions
|
||||
make_context :: proc(#by_ptr desc: Context_Desc) -> Context ---
|
||||
destroy_context :: proc(ctx: Context) ---
|
||||
set_context :: proc(ctx: Context) ---
|
||||
get_context :: proc() -> Context ---
|
||||
default_context :: proc() -> Context ---
|
||||
// drawing functions (call inside sokol-gfx render pass)
|
||||
draw :: proc() ---
|
||||
context_draw :: proc(ctx: Context) ---
|
||||
draw_layer :: proc(#any_int layer_id: c.int) ---
|
||||
context_draw_layer :: proc(ctx: Context, #any_int layer_id: c.int) ---
|
||||
// switch render layer
|
||||
layer :: proc(#any_int layer_id: c.int) ---
|
||||
// switch to a different font
|
||||
font :: proc(#any_int font_index: c.int) ---
|
||||
// set a new virtual canvas size in screen pixels
|
||||
canvas :: proc(w: f32, h: f32) ---
|
||||
// set a new origin in character grid coordinates
|
||||
origin :: proc(x: f32, y: f32) ---
|
||||
// cursor movement functions (relative to origin in character grid coordinates)
|
||||
home :: proc() ---
|
||||
pos :: proc(x: f32, y: f32) ---
|
||||
pos_x :: proc(x: f32) ---
|
||||
pos_y :: proc(y: f32) ---
|
||||
move :: proc(dx: f32, dy: f32) ---
|
||||
move_x :: proc(dx: f32) ---
|
||||
move_y :: proc(dy: f32) ---
|
||||
crlf :: proc() ---
|
||||
// set the current text color
|
||||
color3b :: proc(r: u8, g: u8, b: u8) ---
|
||||
color3f :: proc(r: f32, g: f32, b: f32) ---
|
||||
color4b :: proc(r: u8, g: u8, b: u8, a: u8) ---
|
||||
color4f :: proc(r: f32, g: f32, b: f32, a: f32) ---
|
||||
color1i :: proc(rgba: u32) ---
|
||||
// text rendering
|
||||
putc :: proc(c: u8) ---
|
||||
puts :: proc(str: cstring) ---
|
||||
putr :: proc(str: cstring, #any_int len: c.int) ---
|
||||
}
|
||||
|
||||
Log_Item :: enum i32 {
|
||||
OK,
|
||||
MALLOC_FAILED,
|
||||
ADD_COMMIT_LISTENER_FAILED,
|
||||
COMMAND_BUFFER_FULL,
|
||||
CONTEXT_POOL_EXHAUSTED,
|
||||
CANNOT_DESTROY_DEFAULT_CONTEXT,
|
||||
}
|
||||
|
||||
/*
|
||||
sdtx_logger_t
|
||||
|
||||
Used in sdtx_desc_t to provide a custom logging and error reporting
|
||||
callback to sokol-debugtext.
|
||||
*/
|
||||
Logger :: struct {
|
||||
func : proc "c" (a0: cstring, a1: u32, a2: u32, a3: cstring, a4: u32, a5: cstring, a6: rawptr),
|
||||
user_data : rawptr,
|
||||
}
|
||||
|
||||
// a rendering context handle
|
||||
Context :: struct {
|
||||
id : u32,
|
||||
}
|
||||
|
||||
/*
|
||||
sdtx_range is a pointer-size-pair struct used to pass memory
|
||||
blobs into sokol-debugtext. When initialized from a value type
|
||||
(array or struct), use the SDTX_RANGE() macro to build
|
||||
an sdtx_range struct.
|
||||
*/
|
||||
Range :: struct {
|
||||
ptr : rawptr,
|
||||
size : c.size_t,
|
||||
}
|
||||
|
||||
Font_Desc :: struct {
|
||||
data : Range,
|
||||
first_char : u8,
|
||||
last_char : u8,
|
||||
}
|
||||
|
||||
/*
|
||||
sdtx_context_desc_t
|
||||
|
||||
Describes the initialization parameters of a rendering context. Creating
|
||||
additional rendering contexts is useful if you want to render in
|
||||
different sokol-gfx rendering passes, or when rendering several layers
|
||||
of text.
|
||||
*/
|
||||
Context_Desc :: struct {
|
||||
max_commands : c.int,
|
||||
char_buf_size : c.int,
|
||||
canvas_width : f32,
|
||||
canvas_height : f32,
|
||||
tab_width : c.int,
|
||||
color_format : sg.Pixel_Format,
|
||||
depth_format : sg.Pixel_Format,
|
||||
sample_count : c.int,
|
||||
}
|
||||
|
||||
/*
|
||||
sdtx_allocator_t
|
||||
|
||||
Used in sdtx_desc_t to provide custom memory-alloc and -free functions
|
||||
to sokol_debugtext.h. If memory management should be overridden, both the
|
||||
alloc_fn and free_fn function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
Allocator :: struct {
|
||||
alloc_fn : proc "c" (a0: c.size_t, a1: rawptr) -> rawptr,
|
||||
free_fn : proc "c" (a0: rawptr, a1: rawptr),
|
||||
user_data : rawptr,
|
||||
}
|
||||
|
||||
/*
|
||||
sdtx_desc_t
|
||||
|
||||
Describes the sokol-debugtext API initialization parameters. Passed
|
||||
to the sdtx_setup() function.
|
||||
|
||||
NOTE: to populate the fonts item array with builtin fonts, use any
|
||||
of the following functions:
|
||||
|
||||
sdtx_font_kc853()
|
||||
sdtx_font_kc854()
|
||||
sdtx_font_z1013()
|
||||
sdtx_font_cpc()
|
||||
sdtx_font_c64()
|
||||
sdtx_font_oric()
|
||||
*/
|
||||
Desc :: struct {
|
||||
context_pool_size : c.int,
|
||||
printf_buf_size : c.int,
|
||||
fonts : [8]Font_Desc,
|
||||
ctx : Context_Desc,
|
||||
allocator : Allocator,
|
||||
logger : Logger,
|
||||
}
|
||||
|
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_d3d11_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_d3d11_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_d3d11_release.lib
vendored
Normal file
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_d3d11_release.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_gl_debug.lib
vendored
Normal file
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_gl_debug.lib
vendored
Normal file
Binary file not shown.
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_gl_release.lib
vendored
Normal file
BIN
thirdparty/sokol/debugtext/sokol_debugtext_windows_x64_gl_release.lib
vendored
Normal file
Binary file not shown.
4673
thirdparty/sokol/gfx/gfx.odin
vendored
Normal file
4673
thirdparty/sokol/gfx/gfx.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user