Update sokol
This commit is contained in:
parent
05a596746e
commit
71d5ae7619
2
Makefile
2
Makefile
|
@ -171,7 +171,7 @@ tools/libcdb.a:
|
|||
mv $(CDB)/libcdb.a tools
|
||||
|
||||
|
||||
DOCOS = Sound gameobject Game Window physics Profile Time Player Mouse IO timer Log ColorMap sprite
|
||||
DOCOS = Sound gameobject Game Window physics Profile Time Player Mouse IO Log ColorMap sprite SpriteAnim
|
||||
DOCHTML := $(addsuffix .api.html, $(DOCOS))
|
||||
DOCMD := $(addsuffix .api.md, $(DOCOS))
|
||||
|
||||
|
|
|
@ -122,100 +122,95 @@ sprite.inputs.kp2 = function() { this.pos = [-0.5,-1]; };
|
|||
sprite.inputs.kp1 = function() { this.pos = [-1,-1]; };
|
||||
Object.seal(sprite);
|
||||
|
||||
var aseframeset2anim = function(frameset, meta)
|
||||
{
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = meta.image;
|
||||
var dim = meta.size;
|
||||
var SpriteAnim = {
|
||||
gif(path) {
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = path;
|
||||
var frames = cmd(139,path);
|
||||
var yslice = 1/frames;
|
||||
for (var f = 0; f < frames; f++) {
|
||||
var frame = {};
|
||||
frame.rect = {
|
||||
s0: 0,
|
||||
s1: 1,
|
||||
t0: yslice*f,
|
||||
t1: yslice*(f+1)
|
||||
};
|
||||
frame.time = 0.05;
|
||||
anim.frames.push(frame);
|
||||
}
|
||||
anim.loop = true;
|
||||
var dim = cmd(64,path);
|
||||
dim.y /= frames;
|
||||
anim.dim = dim;
|
||||
return anim;
|
||||
},
|
||||
|
||||
var ase_make_frame = function(ase_frame,i) {
|
||||
var f = ase_frame.frame;
|
||||
var frame = {};
|
||||
frame.rect = {
|
||||
s0: f.x/dim.w,
|
||||
s1: (f.x+f.w)/dim.w,
|
||||
t0: f.y/dim.h,
|
||||
t1: (f.y+f.h)/dim.h
|
||||
strip(path, frames) {
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = path;
|
||||
var xslice = 1/frames;
|
||||
for (var f = 0; f < frames; f++) {
|
||||
var frame = {};
|
||||
frame.rect = {s0:xslice*f, s1: xslice*(f+1), t0:0, t1:1};
|
||||
frame.time = 0.05;
|
||||
anim.frames.push(frame);
|
||||
}
|
||||
anim.dim = cmd(64,path);
|
||||
anim.dim.x /= frames;
|
||||
return anim;
|
||||
},
|
||||
|
||||
aseprite(path) {
|
||||
function aseframeset2anim(frameset, meta) {
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = meta.image;
|
||||
var dim = meta.size;
|
||||
|
||||
var ase_make_frame = function(ase_frame,i) {
|
||||
var f = ase_frame.frame;
|
||||
var frame = {};
|
||||
frame.rect = {
|
||||
s0: f.x/dim.w,
|
||||
s1: (f.x+f.w)/dim.w,
|
||||
t0: f.y/dim.h,
|
||||
t1: (f.y+f.h)/dim.h
|
||||
};
|
||||
frame.time = ase_frame.duration / 1000;
|
||||
anim.frames.push(frame);
|
||||
};
|
||||
frame.time = ase_frame.duration / 1000;
|
||||
anim.frames.push(frame);
|
||||
};
|
||||
|
||||
frameset.forEach(ase_make_frame);
|
||||
anim.dim = [frameset[0].sourceSize.x, frameset[0].sourceSize.y];
|
||||
anim.loop = true;
|
||||
return anim;
|
||||
}
|
||||
|
||||
var ase2anim = function(ase)
|
||||
{
|
||||
var json = IO.slurp(ase);
|
||||
json = JSON.parse(json);
|
||||
var frames = Array.isArray(json.frames) ? json.frames : Object.values(json.frames);
|
||||
return aseframeset2anim(json.frames, json.meta);
|
||||
}
|
||||
|
||||
var ase2anims = function(ase)
|
||||
{
|
||||
var json = IO.slurp(ase);
|
||||
json = JSON.parse(json);
|
||||
var anims = {};
|
||||
var frames = Array.isArray(json.frames) ? json.frames : Object.values(json.frames);
|
||||
for (var tag of json.meta.frameTags)
|
||||
anims[tag.name] = aseframeset2anim(frames.slice(tag.from, tag.to+1), json.meta);
|
||||
|
||||
return anims;
|
||||
}
|
||||
|
||||
var gif2anim = function(gif)
|
||||
{
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = gif;
|
||||
var frames = cmd(139,gif);
|
||||
var yslice = 1/frames;
|
||||
for (var f = 0; f < frames; f++) {
|
||||
var frame = {};
|
||||
frame.rect = {
|
||||
s0: 0,
|
||||
s1: 1,
|
||||
t0: yslice*f,
|
||||
t1: yslice*(f+1)
|
||||
frameset.forEach(ase_make_frame);
|
||||
anim.dim = [frameset[0].sourceSize.x, frameset[0].sourceSize.y];
|
||||
anim.loop = true;
|
||||
return anim;
|
||||
};
|
||||
frame.time = 0.05;
|
||||
anim.frames.push(frame);
|
||||
}
|
||||
anim.loop = true;
|
||||
var dim = cmd(64,gif);
|
||||
dim.y /= frames;
|
||||
anim.dim = dim;
|
||||
return anim;
|
||||
}
|
||||
|
||||
var strip2anim = function(strip)
|
||||
{
|
||||
var anim = {};
|
||||
anim.frames = [];
|
||||
anim.path = strip;
|
||||
var frames = 8;
|
||||
var xslice = 1/frames;
|
||||
for (var f = 0; f < frames; f++) {
|
||||
var frame = {};
|
||||
frame.rect = {s0:xslice*f, s1: slice*(f+1), t0:0, t1:1};
|
||||
frame.time = 0.05;
|
||||
anim.frames.push(frame);
|
||||
}
|
||||
anim.dim = cmd(64,strip);
|
||||
anim.dim.x /= frames;
|
||||
return anim;
|
||||
}
|
||||
var json = IO.slurp(ase);
|
||||
json = JSON.parse(json);
|
||||
var anims = {};
|
||||
var frames = Array.isArray(json.frames) ? json.frames : Object.values(json.frames);
|
||||
for (var tag of json.meta.frameTags)
|
||||
anims[tag.name] = aseframeset2anim(frames.slice(tag.from, tag.to+1), json.meta);
|
||||
|
||||
return anims;
|
||||
},
|
||||
};
|
||||
|
||||
SpriteAnim.doc = 'Functions to create Primum animations from varying sources.';
|
||||
SpriteAnim.gif.doc = 'Convert a gif.';
|
||||
SpriteAnim.strip.doc = 'Given a path and number of frames, converts a horizontal strip animation, where each cell is the same width.'
|
||||
SpriteAnim.aseprite.doc = 'Given an aseprite json metadata, returns an object of animations defined in the aseprite file.';
|
||||
|
||||
/* Container to play sprites and anim2ds */
|
||||
component.char2d = Object.copy(sprite, {
|
||||
component.char2d = Object.copy(component, {
|
||||
get enabled() { return cmd(114,this.id); },
|
||||
set enabled(x) { cmd(20,this.id,x); },
|
||||
set color(x) { cmd(96,this.id,x); },
|
||||
|
||||
get pos() { return cmd(111, this.id); },
|
||||
set pos(x) { cmd(37,this.id,x); },
|
||||
set layer(x) { cmd(60, this.id, x); },
|
||||
|
@ -235,18 +230,15 @@ component.char2d = Object.copy(sprite, {
|
|||
cmd(12,this.id,this.path,this.rect);
|
||||
},
|
||||
|
||||
kill() { cmd(9,this.id); },
|
||||
ur: {
|
||||
|
||||
},
|
||||
|
||||
make(go) {
|
||||
Log.say('creating animation');
|
||||
var char = Object.create(this);
|
||||
char.gameobject = go;
|
||||
Object.assign(char, make_sprite(go.body));
|
||||
char.frame = 0;
|
||||
char.timer = timer.make(char.advance.bind(char), 1);
|
||||
char.timer.loop = true;
|
||||
Object.hide(char, 'timer');
|
||||
return char;
|
||||
},
|
||||
|
||||
|
@ -308,6 +300,17 @@ component.char2d = Object.copy(sprite, {
|
|||
},
|
||||
});
|
||||
|
||||
component.char2d.impl = {
|
||||
get enabled() { return cmd(114,this.id); },
|
||||
set enabled(x) { cmd(20,this.id,x); },
|
||||
set color(x) { cmd(96,this.id,x); },
|
||||
|
||||
get pos() { return cmd(111, this.id); },
|
||||
set pos(x) { cmd(37,this.id,x); },
|
||||
set layer(x) { cmd(60, this.id, x); },
|
||||
get layer() { return this.gameobject.draw_layer; },
|
||||
};
|
||||
|
||||
/* Returns points specifying this geometry, with ccw */
|
||||
var Geometry = {
|
||||
box(w, h) {
|
||||
|
|
|
@ -35,7 +35,7 @@ static FILE *sout;
|
|||
void log_init()
|
||||
{
|
||||
consolelog = malloc(CONSOLE_BUF+1);
|
||||
sout = fdopen(dup(stdout),"w");
|
||||
sout = fdopen(dup(1),"w");
|
||||
sout = stdout;
|
||||
}
|
||||
|
||||
|
|
703
source/engine/thirdparty/sokol/sokol_app.h
vendored
703
source/engine/thirdparty/sokol/sokol_app.h
vendored
|
@ -951,9 +951,11 @@
|
|||
|
||||
OPTIONAL: DON'T HIJACK main() (#define SOKOL_NO_ENTRY)
|
||||
======================================================
|
||||
NOTE: SOKOL_NO_ENTRY and sapp_run() is currently not supported on Android.
|
||||
|
||||
In its default configuration, sokol_app.h "hijacks" the platform's
|
||||
standard main() function. This was done because different platforms
|
||||
have different main functions which are not compatible with
|
||||
have different entry point conventions which are not compatible with
|
||||
C's main() (for instance WinMain on Windows has completely different
|
||||
arguments). However, this "main hijacking" posed a problem for
|
||||
usage scenarios like integrating sokol_app.h with other languages than
|
||||
|
@ -965,12 +967,30 @@
|
|||
- instead provide the standard main() function of the platform
|
||||
- from the main function, call the function ```sapp_run()``` which
|
||||
takes a pointer to an ```sapp_desc``` structure.
|
||||
- ```sapp_run()``` takes over control and calls the provided init-, frame-,
|
||||
shutdown- and event-callbacks just like in the default model, it
|
||||
will only return when the application quits (or not at all on some
|
||||
platforms, like emscripten)
|
||||
- from here on```sapp_run()``` takes over control and calls the provided
|
||||
init-, frame-, event- and cleanup-callbacks just like in the default model.
|
||||
|
||||
NOTE: SOKOL_NO_ENTRY is currently not supported on Android.
|
||||
sapp_run() behaves differently across platforms:
|
||||
|
||||
- on some platforms, sapp_run() will return when the application quits
|
||||
- on other platforms, sapp_run() will never return, even when the
|
||||
application quits (the operating system is free to simply terminate
|
||||
the application at any time)
|
||||
- on Emscripten specifically, sapp_run() will return immediately while
|
||||
the frame callback keeps being called
|
||||
|
||||
This different behaviour of sapp_run() essentially means that there shouldn't
|
||||
be any code *after* sapp_run(), because that may either never be called, or in
|
||||
case of Emscripten will be called at an unexpected time (at application start).
|
||||
|
||||
An application also should not depend on the cleanup-callback being called
|
||||
when cross-platform compatibility is required.
|
||||
|
||||
Since sapp_run() returns immediately on Emscripten you shouldn't activate
|
||||
the 'EXIT_RUNTIME' linker option (this is disabled by default when compiling
|
||||
for the browser target), since the C/C++ exit runtime would be called immediately at
|
||||
application start, causing any global objects to be destroyed and global
|
||||
variables to be zeroed.
|
||||
|
||||
WINDOWS CONSOLE OUTPUT
|
||||
======================
|
||||
|
@ -1019,8 +1039,8 @@
|
|||
return (sapp_desc){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc = my_alloc,
|
||||
.free = my_free,
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
};
|
||||
|
@ -1473,12 +1493,12 @@ typedef struct sapp_icon_desc {
|
|||
|
||||
Used in sapp_desc to provide custom memory-alloc and -free functions
|
||||
to sokol_app.h. If memory management should be overridden, both the
|
||||
alloc and free function must be provided (e.g. it's not valid to
|
||||
alloc_fn and free_fn function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
typedef struct sapp_allocator {
|
||||
void* (*alloc)(size_t size, void* user_data);
|
||||
void (*free)(void* ptr, void* user_data);
|
||||
void* (*alloc_fn)(size_t size, void* user_data);
|
||||
void (*free_fn)(void* ptr, void* user_data);
|
||||
void* user_data;
|
||||
} sapp_allocator;
|
||||
|
||||
|
@ -1573,6 +1593,18 @@ typedef struct sapp_allocator {
|
|||
_SAPP_LOGITEM_XMACRO(ANDROID_NATIVE_ACTIVITY_ONCREATE, "NativeActivity onCreate") \
|
||||
_SAPP_LOGITEM_XMACRO(ANDROID_CREATE_THREAD_PIPE_FAILED, "failed to create thread pipe") \
|
||||
_SAPP_LOGITEM_XMACRO(ANDROID_NATIVE_ACTIVITY_CREATE_SUCCESS, "NativeActivity sucessfully created") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_SURFACE_FAILED, "wgpu: failed to create surface for swapchain") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_SWAPCHAIN_FAILED, "wgpu: failed to create swapchain object") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_TEXTURE_FAILED, "wgpu: failed to create depth-stencil texture for swapchain") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_VIEW_FAILED, "wgpu: failed to create view object for swapchain depth-stencil texture") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_MSAA_TEXTURE_FAILED, "wgpu: failed to create msaa texture for swapchain") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_MSAA_VIEW_FAILED, "wgpu: failed to create view object for swapchain msaa texture") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_REQUEST_DEVICE_STATUS_ERROR, "wgpu: requesting device failed with status 'error'") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_REQUEST_DEVICE_STATUS_UNKNOWN, "wgpu: requesting device failed with status 'unknown'") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_UNAVAILABLE, "wgpu: requesting adapter failed with 'unavailable'") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_ERROR, "wgpu: requesting adapter failed with status 'error'") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN, "wgpu: requesting adapter failed with status 'unknown'") \
|
||||
_SAPP_LOGITEM_XMACRO(WGPU_CREATE_INSTANCE_FAILED, "wgpu: failed to create instance") \
|
||||
_SAPP_LOGITEM_XMACRO(IMAGE_DATA_SIZE_MISMATCH, "image data size mismatch (must be width*height*4 bytes)") \
|
||||
_SAPP_LOGITEM_XMACRO(DROPPED_FILE_PATH_TOO_LONG, "dropped file path too long (sapp_desc.max_dropped_filed_path_length)") \
|
||||
_SAPP_LOGITEM_XMACRO(CLIPBOARD_STRING_TOO_BIG, "clipboard string didn't fit into clipboard buffer") \
|
||||
|
@ -1852,7 +1884,31 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
|
|||
#include <stddef.h> // size_t
|
||||
#include <math.h> // roundf
|
||||
|
||||
/* check if the config defines are alright */
|
||||
// helper macros
|
||||
#define _sapp_def(val, def) (((val) == 0) ? (def) : (val))
|
||||
#define _sapp_absf(a) (((a)<0.0f)?-(a):(a))
|
||||
|
||||
#define _SAPP_MAX_TITLE_LENGTH (128)
|
||||
#define _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH (640)
|
||||
#define _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT (480)
|
||||
// NOTE: the pixel format values *must* be compatible with sg_pixel_format
|
||||
#define _SAPP_PIXELFORMAT_RGBA8 (23)
|
||||
#define _SAPP_PIXELFORMAT_BGRA8 (28)
|
||||
#define _SAPP_PIXELFORMAT_DEPTH (42)
|
||||
#define _SAPP_PIXELFORMAT_DEPTH_STENCIL (43)
|
||||
|
||||
#if defined(_SAPP_MACOS) || defined(_SAPP_IOS)
|
||||
// this is ARC compatible
|
||||
#if defined(__cplusplus)
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = type(); }
|
||||
#else
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
|
||||
#endif
|
||||
#else
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { _sapp_clear(&item, sizeof(item)); }
|
||||
#endif
|
||||
|
||||
// check if the config defines are alright
|
||||
#if defined(__APPLE__)
|
||||
// see https://clang.llvm.org/docs/LanguageExtensions.html#automatic-reference-counting
|
||||
#if !defined(__cplusplus)
|
||||
|
@ -2339,15 +2395,18 @@ typedef struct {
|
|||
|
||||
#if defined(SOKOL_WGPU)
|
||||
typedef struct {
|
||||
int state;
|
||||
WGPUInstance instance;
|
||||
WGPUAdapter adapter;
|
||||
WGPUDevice device;
|
||||
WGPUSwapChain swapchain;
|
||||
WGPUTextureFormat render_format;
|
||||
WGPUSurface surface;
|
||||
WGPUSwapChain swapchain;
|
||||
WGPUTexture msaa_tex;
|
||||
WGPUTexture depth_stencil_tex;
|
||||
WGPUTextureView swapchain_view;
|
||||
WGPUTextureView msaa_view;
|
||||
WGPUTexture depth_stencil_tex;
|
||||
WGPUTextureView depth_stencil_view;
|
||||
WGPUTextureView swapchain_view;
|
||||
bool async_init_done;
|
||||
} _sapp_wgpu_t;
|
||||
#endif
|
||||
|
||||
|
@ -2357,9 +2416,6 @@ typedef struct {
|
|||
bool wants_hide_keyboard;
|
||||
bool mouse_lock_requested;
|
||||
uint16_t mouse_buttons;
|
||||
#if defined(SOKOL_WGPU)
|
||||
_sapp_wgpu_t wgpu;
|
||||
#endif
|
||||
} _sapp_emsc_t;
|
||||
#endif // _SAPP_EMSCRIPTEN
|
||||
|
||||
|
@ -2396,7 +2452,7 @@ typedef enum MONITOR_DPI_TYPE {
|
|||
MDT_RAW_DPI = 2,
|
||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||
} MONITOR_DPI_TYPE;
|
||||
#endif /*DPI_ENUMS_DECLARED*/
|
||||
#endif // DPI_ENUMS_DECLARED
|
||||
|
||||
typedef struct {
|
||||
bool aware;
|
||||
|
@ -2683,30 +2739,6 @@ typedef struct {
|
|||
|
||||
#endif // _SAPP_LINUX
|
||||
|
||||
/* helper macros */
|
||||
#define _sapp_def(val, def) (((val) == 0) ? (def) : (val))
|
||||
#define _sapp_absf(a) (((a)<0.0f)?-(a):(a))
|
||||
|
||||
#define _SAPP_MAX_TITLE_LENGTH (128)
|
||||
#define _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH (640)
|
||||
#define _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT (480)
|
||||
/* NOTE: the pixel format values *must* be compatible with sg_pixel_format */
|
||||
#define _SAPP_PIXELFORMAT_RGBA8 (23)
|
||||
#define _SAPP_PIXELFORMAT_BGRA8 (28)
|
||||
#define _SAPP_PIXELFORMAT_DEPTH (42)
|
||||
#define _SAPP_PIXELFORMAT_DEPTH_STENCIL (43)
|
||||
|
||||
#if defined(_SAPP_MACOS) || defined(_SAPP_IOS)
|
||||
// this is ARC compatible
|
||||
#if defined(__cplusplus)
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = type(); }
|
||||
#else
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; }
|
||||
#endif
|
||||
#else
|
||||
#define _SAPP_CLEAR_ARC_STRUCT(type, item) { _sapp_clear(&item, sizeof(item)); }
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
int buf_size;
|
||||
|
@ -2764,6 +2796,9 @@ typedef struct {
|
|||
_sapp_ios_t ios;
|
||||
#elif defined(_SAPP_EMSCRIPTEN)
|
||||
_sapp_emsc_t emsc;
|
||||
#if defined(SOKOL_WGPU)
|
||||
_sapp_wgpu_t wgpu;
|
||||
#endif
|
||||
#elif defined(_SAPP_WIN32)
|
||||
_sapp_win32_t win32;
|
||||
#if defined(SOKOL_D3D11)
|
||||
|
@ -2782,8 +2817,8 @@ typedef struct {
|
|||
#endif
|
||||
#endif
|
||||
char html5_canvas_selector[_SAPP_MAX_TITLE_LENGTH];
|
||||
char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */
|
||||
wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */
|
||||
char window_title[_SAPP_MAX_TITLE_LENGTH]; // UTF-8
|
||||
wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; // UTF-32 or UCS-2 */
|
||||
sapp_keycode keycodes[SAPP_MAX_KEYCODES];
|
||||
} _sapp_t;
|
||||
static _sapp_t _sapp;
|
||||
|
@ -2842,10 +2877,9 @@ _SOKOL_PRIVATE void _sapp_clear(void* ptr, size_t size) {
|
|||
_SOKOL_PRIVATE void* _sapp_malloc(size_t size) {
|
||||
SOKOL_ASSERT(size > 0);
|
||||
void* ptr;
|
||||
if (_sapp.desc.allocator.alloc) {
|
||||
ptr = _sapp.desc.allocator.alloc(size, _sapp.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_sapp.desc.allocator.alloc_fn) {
|
||||
ptr = _sapp.desc.allocator.alloc_fn(size, _sapp.desc.allocator.user_data);
|
||||
} else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
if (0 == ptr) {
|
||||
|
@ -2861,8 +2895,8 @@ _SOKOL_PRIVATE void* _sapp_malloc_clear(size_t size) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_free(void* ptr) {
|
||||
if (_sapp.desc.allocator.free) {
|
||||
_sapp.desc.allocator.free(ptr, _sapp.desc.allocator.user_data);
|
||||
if (_sapp.desc.allocator.free_fn) {
|
||||
_sapp.desc.allocator.free_fn(ptr, _sapp.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
free(ptr);
|
||||
|
@ -2966,7 +3000,7 @@ _SOKOL_PRIVATE bool _sapp_strcpy(const char* src, char* dst, int max_len) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE sapp_desc _sapp_desc_defaults(const sapp_desc* desc) {
|
||||
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
|
||||
SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
|
||||
sapp_desc res = *desc;
|
||||
res.sample_count = _sapp_def(res.sample_count, 1);
|
||||
res.swap_interval = _sapp_def(res.swap_interval, 1);
|
||||
|
@ -3437,50 +3471,6 @@ _SOKOL_PRIVATE void _sapp_macos_run(const sapp_desc* desc) {
|
|||
// set the application dock icon as early as possible, otherwise
|
||||
// the dummy icon will be visible for a short time
|
||||
sapp_set_icon(&_sapp.desc.icon);
|
||||
|
||||
NSMenu* menu_bar = [[NSMenu alloc] init];
|
||||
NSMenuItem* app_menu_item = [[NSMenuItem alloc] init];
|
||||
[menu_bar addItem:app_menu_item];
|
||||
NSApp.mainMenu = menu_bar;
|
||||
NSMenu* app_menu = [[NSMenu alloc] init];
|
||||
NSString* window_title_as_nsstring = [NSString stringWithUTF8String:desc->window_title];
|
||||
|
||||
NSString* quit_title = [@"Quit " stringByAppendingString:window_title_as_nsstring];
|
||||
NSMenuItem* quit_menu_item = [[NSMenuItem alloc]
|
||||
initWithTitle:quit_title
|
||||
action:@selector(terminate:)
|
||||
keyEquivalent:@"q"];
|
||||
|
||||
NSString* hide_title = [@"Hide " stringByAppendingString:window_title_as_nsstring];
|
||||
NSMenuItem* hide_menu_item = [[NSMenuItem alloc]
|
||||
initWithTitle:hide_title
|
||||
action:@selector(hide:)
|
||||
keyEquivalent:@"h"];
|
||||
|
||||
NSMenuItem* hide_others_item = [[NSMenuItem alloc]
|
||||
initWithTitle:@"Hide Others"
|
||||
action:@selector(hideOtherApplications:)
|
||||
keyEquivalent:@"h"];
|
||||
|
||||
[hide_others_item setKeyEquivalentModifierMask: NSEventModifierFlagOption];
|
||||
|
||||
NSMenuItem* show_all_item = [[NSMenuItem alloc]
|
||||
initWithTitle:@"Show All"
|
||||
action:@selector(unhideAllApplications:)
|
||||
keyEquivalent:@""];
|
||||
|
||||
[app_menu addItem:hide_menu_item];
|
||||
[app_menu addItem:hide_others_item];
|
||||
[app_menu addItem:show_all_item];
|
||||
[app_menu addItem:[NSMenuItem separatorItem]];
|
||||
[app_menu addItem:quit_menu_item];
|
||||
app_menu_item.submenu = app_menu;
|
||||
|
||||
_SAPP_OBJC_RELEASE(window_title_as_nsstring);
|
||||
_SAPP_OBJC_RELEASE(app_menu);
|
||||
_SAPP_OBJC_RELEASE(app_menu_item);
|
||||
_SAPP_OBJC_RELEASE(menu_bar);
|
||||
|
||||
_sapp.macos.app_dlg = [[_sapp_macos_app_delegate alloc] init];
|
||||
NSApp.delegate = _sapp.macos.app_dlg;
|
||||
|
||||
|
@ -5075,11 +5065,6 @@ _SOKOL_PRIVATE void _sapp_emsc_set_icon(const sapp_icon_desc* icon_desc, int num
|
|||
sapp_js_set_favicon(img_desc->width, img_desc->height, (const uint8_t*) img_desc->pixels.ptr);
|
||||
}
|
||||
|
||||
#if defined(SOKOL_WGPU)
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_create(void);
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_discard(void);
|
||||
#endif
|
||||
|
||||
_SOKOL_PRIVATE uint32_t _sapp_emsc_mouse_button_mods(uint16_t buttons) {
|
||||
uint32_t m = 0;
|
||||
if (0 != (buttons & (1<<0))) { m |= SAPP_MODIFIER_LMB; }
|
||||
|
@ -5118,6 +5103,10 @@ _SOKOL_PRIVATE uint32_t _sapp_emsc_touch_event_mods(const EmscriptenTouchEvent*
|
|||
return m;
|
||||
}
|
||||
|
||||
#if defined(SOKOL_WGPU)
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_size_changed(void);
|
||||
#endif
|
||||
|
||||
_SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenUiEvent* ui_event, void* user_data) {
|
||||
_SOKOL_UNUSED(event_type);
|
||||
_SOKOL_UNUSED(user_data);
|
||||
|
@ -5163,9 +5152,8 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenU
|
|||
SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0));
|
||||
emscripten_set_canvas_element_size(_sapp.html5_canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height);
|
||||
#if defined(SOKOL_WGPU)
|
||||
/* on WebGPU: recreate size-dependent rendering surfaces */
|
||||
_sapp_emsc_wgpu_surfaces_discard();
|
||||
_sapp_emsc_wgpu_surfaces_create();
|
||||
// on WebGPU: recreate size-dependent rendering surfaces
|
||||
_sapp_emsc_wgpu_size_changed();
|
||||
#endif
|
||||
if (_sapp_events_enabled()) {
|
||||
_sapp_init_event(SAPP_EVENTTYPE_RESIZED);
|
||||
|
@ -5437,11 +5425,10 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboard
|
|||
_sapp.event.key_code = _sapp_emsc_translate_key(emsc_event->key);
|
||||
}
|
||||
|
||||
/* Special hack for macOS: if the Super key is pressed, macOS doesn't
|
||||
send keyUp events. As a workaround, to prevent keys from
|
||||
"sticking", we'll send a keyup event following a keydown
|
||||
when the SUPER key is pressed
|
||||
*/
|
||||
// Special hack for macOS: if the Super key is pressed, macOS doesn't
|
||||
// send keyUp events. As a workaround, to prevent keys from
|
||||
// "sticking", we'll send a keyup event following a keydown
|
||||
// when the SUPER key is pressed
|
||||
if ((type == SAPP_EVENTTYPE_KEY_DOWN) &&
|
||||
(_sapp.event.key_code != SAPP_KEYCODE_LEFT_SUPER) &&
|
||||
(_sapp.event.key_code != SAPP_KEYCODE_RIGHT_SUPER) &&
|
||||
|
@ -5636,114 +5623,184 @@ _SOKOL_PRIVATE void _sapp_emsc_webgl_init(void) {
|
|||
#endif
|
||||
|
||||
#if defined(SOKOL_WGPU)
|
||||
#define _SAPP_EMSC_WGPU_STATE_INITIAL (0)
|
||||
#define _SAPP_EMSC_WGPU_STATE_READY (1)
|
||||
#define _SAPP_EMSC_WGPU_STATE_RUNNING (2)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/* called when the asynchronous WebGPU device + swapchain init code in JS has finished */
|
||||
EMSCRIPTEN_KEEPALIVE void _sapp_emsc_wgpu_ready(int device_id, int swapchain_id, int swapchain_fmt) {
|
||||
SOKOL_ASSERT(0 == _sapp.emsc.wgpu.device);
|
||||
_sapp.emsc.wgpu.device = (WGPUDevice) device_id;
|
||||
_sapp.emsc.wgpu.swapchain = (WGPUSwapChain) swapchain_id;
|
||||
_sapp.emsc.wgpu.render_format = (WGPUTextureFormat) swapchain_fmt;
|
||||
_sapp.emsc.wgpu.state = _SAPP_EMSC_WGPU_STATE_READY;
|
||||
}
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_create_swapchain(void) {
|
||||
SOKOL_ASSERT(_sapp.wgpu.instance);
|
||||
SOKOL_ASSERT(_sapp.wgpu.device);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.surface);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.swapchain);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.msaa_tex);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.msaa_view);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.depth_stencil_tex);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.depth_stencil_view);
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.swapchain_view);
|
||||
|
||||
/* embedded JS function to handle all the asynchronous WebGPU setup */
|
||||
EM_JS(void, sapp_js_wgpu_init, (), {
|
||||
WebGPU.initManagers();
|
||||
// FIXME: the extension activation must be more clever here
|
||||
navigator.gpu.requestAdapter().then((adapter) => {
|
||||
console.log("wgpu adapter extensions: " + adapter.extensions);
|
||||
adapter.requestDevice({ extensions: ["textureCompressionBC"]}).then((device) => {
|
||||
var gpuContext = document.getElementById("canvas").getContext("gpupresent");
|
||||
console.log("wgpu device extensions: " + adapter.extensions);
|
||||
gpuContext.getSwapChainPreferredFormat(device).then((fmt) => {
|
||||
const swapChainDescriptor = { device: device, format: fmt };
|
||||
const swapChain = gpuContext.configureSwapChain(swapChainDescriptor);
|
||||
const deviceId = WebGPU.mgrDevice.create(device);
|
||||
const swapChainId = WebGPU.mgrSwapChain.create(swapChain);
|
||||
const fmtId = WebGPU.TextureFormat.findIndex(function(elm) { return elm==fmt; });
|
||||
console.log("wgpu device: " + device);
|
||||
console.log("wgpu swap chain: " + swapChain);
|
||||
console.log("wgpu preferred format: " + fmt + " (" + fmtId + ")");
|
||||
__sapp_emsc_wgpu_ready(deviceId, swapChainId, fmtId);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
WGPUSurfaceDescriptorFromCanvasHTMLSelector canvas_desc;
|
||||
_sapp_clear(&canvas_desc, sizeof(canvas_desc));
|
||||
canvas_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
||||
canvas_desc.selector = _sapp.html5_canvas_selector;
|
||||
WGPUSurfaceDescriptor surf_desc;
|
||||
_sapp_clear(&surf_desc, sizeof(surf_desc));
|
||||
surf_desc.nextInChain = &canvas_desc.chain;
|
||||
_sapp.wgpu.surface = wgpuInstanceCreateSurface(_sapp.wgpu.instance, &surf_desc);
|
||||
if (0 == _sapp.wgpu.surface) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_SURFACE_FAILED);
|
||||
}
|
||||
_sapp.wgpu.render_format = wgpuSurfaceGetPreferredFormat(_sapp.wgpu.surface, _sapp.wgpu.adapter);
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_create(void) {
|
||||
SOKOL_ASSERT(_sapp.emsc.wgpu.device);
|
||||
SOKOL_ASSERT(_sapp.emsc.wgpu.swapchain);
|
||||
SOKOL_ASSERT(0 == _sapp.emsc.wgpu.depth_stencil_tex);
|
||||
SOKOL_ASSERT(0 == _sapp.emsc.wgpu.depth_stencil_view);
|
||||
SOKOL_ASSERT(0 == _sapp.emsc.wgpu.msaa_tex);
|
||||
SOKOL_ASSERT(0 == _sapp.emsc.wgpu.msaa_view);
|
||||
WGPUSwapChainDescriptor sc_desc;
|
||||
_sapp_clear(&sc_desc, sizeof(sc_desc));
|
||||
sc_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
sc_desc.format = _sapp.wgpu.render_format;
|
||||
sc_desc.width = (uint32_t)_sapp.framebuffer_width;
|
||||
sc_desc.height = (uint32_t)_sapp.framebuffer_height;
|
||||
sc_desc.presentMode = WGPUPresentMode_Fifo;
|
||||
_sapp.wgpu.swapchain = wgpuDeviceCreateSwapChain(_sapp.wgpu.device, _sapp.wgpu.surface, &sc_desc);
|
||||
if (0 == _sapp.wgpu.swapchain) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_SWAPCHAIN_FAILED);
|
||||
}
|
||||
|
||||
WGPUTextureDescriptor ds_desc;
|
||||
_sapp_clear(&ds_desc, sizeof(ds_desc));
|
||||
ds_desc.usage = WGPUTextureUsage_OutputAttachment;
|
||||
ds_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
ds_desc.dimension = WGPUTextureDimension_2D;
|
||||
ds_desc.size.width = (uint32_t) _sapp.framebuffer_width;
|
||||
ds_desc.size.height = (uint32_t) _sapp.framebuffer_height;
|
||||
ds_desc.size.depth = 1;
|
||||
ds_desc.arrayLayerCount = 1;
|
||||
ds_desc.format = WGPUTextureFormat_Depth24PlusStencil8;
|
||||
ds_desc.size.width = (uint32_t)_sapp.framebuffer_width;
|
||||
ds_desc.size.height = (uint32_t)_sapp.framebuffer_height;
|
||||
ds_desc.size.depthOrArrayLayers = 1;
|
||||
ds_desc.format = WGPUTextureFormat_Depth32FloatStencil8;
|
||||
ds_desc.mipLevelCount = 1;
|
||||
ds_desc.sampleCount = _sapp.sample_count;
|
||||
_sapp.emsc.wgpu.depth_stencil_tex = wgpuDeviceCreateTexture(_sapp.emsc.wgpu.device, &ds_desc);
|
||||
_sapp.emsc.wgpu.depth_stencil_view = wgpuTextureCreateView(_sapp.emsc.wgpu.depth_stencil_tex, 0);
|
||||
ds_desc.sampleCount = (uint32_t)_sapp.sample_count;
|
||||
_sapp.wgpu.depth_stencil_tex = wgpuDeviceCreateTexture(_sapp.wgpu.device, &ds_desc);
|
||||
if (0 == _sapp.wgpu.depth_stencil_tex) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_TEXTURE_FAILED);
|
||||
}
|
||||
_sapp.wgpu.depth_stencil_view = wgpuTextureCreateView(_sapp.wgpu.depth_stencil_tex, 0);
|
||||
if (0 == _sapp.wgpu.depth_stencil_view) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_VIEW_FAILED);
|
||||
}
|
||||
|
||||
if (_sapp.sample_count > 1) {
|
||||
WGPUTextureDescriptor msaa_desc;
|
||||
_sapp_clear(&msaa_desc, sizeof(msaa_desc));
|
||||
msaa_desc.usage = WGPUTextureUsage_OutputAttachment;
|
||||
msaa_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
msaa_desc.dimension = WGPUTextureDimension_2D;
|
||||
msaa_desc.size.width = (uint32_t) _sapp.framebuffer_width;
|
||||
msaa_desc.size.height = (uint32_t) _sapp.framebuffer_height;
|
||||
msaa_desc.size.depth = 1;
|
||||
msaa_desc.arrayLayerCount = 1;
|
||||
msaa_desc.format = _sapp.emsc.wgpu.render_format;
|
||||
msaa_desc.size.width = (uint32_t)_sapp.framebuffer_width;
|
||||
msaa_desc.size.height = (uint32_t)_sapp.framebuffer_height;
|
||||
msaa_desc.size.depthOrArrayLayers = 1;
|
||||
msaa_desc.format = _sapp.wgpu.render_format;
|
||||
msaa_desc.mipLevelCount = 1;
|
||||
msaa_desc.sampleCount = _sapp.sample_count;
|
||||
_sapp.emsc.wgpu.msaa_tex = wgpuDeviceCreateTexture(_sapp.emsc.wgpu.device, &msaa_desc);
|
||||
_sapp.emsc.wgpu.msaa_view = wgpuTextureCreateView(_sapp.emsc.wgpu.msaa_tex, 0);
|
||||
msaa_desc.sampleCount = (uint32_t)_sapp.sample_count;
|
||||
_sapp.wgpu.msaa_tex = wgpuDeviceCreateTexture(_sapp.wgpu.device, &msaa_desc);
|
||||
if (0 == _sapp.wgpu.msaa_tex) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_MSAA_TEXTURE_FAILED);
|
||||
}
|
||||
_sapp.wgpu.msaa_view = wgpuTextureCreateView(_sapp.wgpu.msaa_tex, 0);
|
||||
if (0 == _sapp.wgpu.msaa_view) {
|
||||
_SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_MSAA_VIEW_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_discard(void) {
|
||||
if (_sapp.emsc.wgpu.msaa_tex) {
|
||||
wgpuTextureRelease(_sapp.emsc.wgpu.msaa_tex);
|
||||
_sapp.emsc.wgpu.msaa_tex = 0;
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_discard_swapchain(void) {
|
||||
if (_sapp.wgpu.msaa_view) {
|
||||
wgpuTextureViewRelease(_sapp.wgpu.msaa_view);
|
||||
_sapp.wgpu.msaa_view = 0;
|
||||
}
|
||||
if (_sapp.emsc.wgpu.msaa_view) {
|
||||
wgpuTextureViewRelease(_sapp.emsc.wgpu.msaa_view);
|
||||
_sapp.emsc.wgpu.msaa_view = 0;
|
||||
if (_sapp.wgpu.msaa_tex) {
|
||||
wgpuTextureRelease(_sapp.wgpu.msaa_tex);
|
||||
_sapp.wgpu.msaa_tex = 0;
|
||||
}
|
||||
if (_sapp.emsc.wgpu.depth_stencil_tex) {
|
||||
wgpuTextureRelease(_sapp.emsc.wgpu.depth_stencil_tex);
|
||||
_sapp.emsc.wgpu.depth_stencil_tex = 0;
|
||||
if (_sapp.wgpu.depth_stencil_view) {
|
||||
wgpuTextureViewRelease(_sapp.wgpu.depth_stencil_view);
|
||||
_sapp.wgpu.depth_stencil_view = 0;
|
||||
}
|
||||
if (_sapp.emsc.wgpu.depth_stencil_view) {
|
||||
wgpuTextureViewRelease(_sapp.emsc.wgpu.depth_stencil_view);
|
||||
_sapp.emsc.wgpu.depth_stencil_view = 0;
|
||||
if (_sapp.wgpu.depth_stencil_tex) {
|
||||
wgpuTextureRelease(_sapp.wgpu.depth_stencil_tex);
|
||||
_sapp.wgpu.depth_stencil_tex = 0;
|
||||
}
|
||||
if (_sapp.wgpu.swapchain) {
|
||||
wgpuSwapChainRelease(_sapp.wgpu.swapchain);
|
||||
_sapp.wgpu.swapchain = 0;
|
||||
}
|
||||
if (_sapp.wgpu.surface) {
|
||||
wgpuSurfaceRelease(_sapp.wgpu.surface);
|
||||
_sapp.wgpu.surface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_next_frame(void) {
|
||||
if (_sapp.emsc.wgpu.swapchain_view) {
|
||||
wgpuTextureViewRelease(_sapp.emsc.wgpu.swapchain_view);
|
||||
}
|
||||
_sapp.emsc.wgpu.swapchain_view = wgpuSwapChainGetCurrentTextureView(_sapp.emsc.wgpu.swapchain);
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_size_changed(void) {
|
||||
_sapp_emsc_wgpu_discard_swapchain();
|
||||
_sapp_emsc_wgpu_create_swapchain();
|
||||
}
|
||||
#endif
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_request_device_cb(WGPURequestDeviceStatus status, WGPUDevice device, const char* msg, void* userdata) {
|
||||
_SOKOL_UNUSED(msg);
|
||||
_SOKOL_UNUSED(userdata);
|
||||
SOKOL_ASSERT(!_sapp.wgpu.async_init_done);
|
||||
if (status != WGPURequestDeviceStatus_Success) {
|
||||
if (status == WGPURequestDeviceStatus_Error) {
|
||||
_SAPP_PANIC(WGPU_REQUEST_DEVICE_STATUS_ERROR);
|
||||
} else {
|
||||
_SAPP_PANIC(WGPU_REQUEST_DEVICE_STATUS_UNKNOWN);
|
||||
}
|
||||
}
|
||||
SOKOL_ASSERT(device);
|
||||
_sapp.wgpu.device = device;
|
||||
_sapp_emsc_wgpu_create_swapchain();
|
||||
_sapp.wgpu.async_init_done = true;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_request_adapter_cb(WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* msg, void* userdata) {
|
||||
_SOKOL_UNUSED(msg);
|
||||
_SOKOL_UNUSED(userdata);
|
||||
if (status != WGPURequestAdapterStatus_Success) {
|
||||
switch (status) {
|
||||
case WGPURequestAdapterStatus_Unavailable: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_UNAVAILABLE); break;
|
||||
case WGPURequestAdapterStatus_Error: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_ERROR); break;
|
||||
default: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN); break;
|
||||
}
|
||||
}
|
||||
SOKOL_ASSERT(adapter);
|
||||
_sapp.wgpu.adapter = adapter;
|
||||
size_t cur_feature_index = 1;
|
||||
WGPUFeatureName requiredFeatures[8] = {
|
||||
WGPUFeatureName_Depth32FloatStencil8,
|
||||
};
|
||||
// check for optional features we're interested in
|
||||
// FIXME: ASTC texture compression
|
||||
if (wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionBC)) {
|
||||
requiredFeatures[cur_feature_index++] = WGPUFeatureName_TextureCompressionBC;
|
||||
} else if (wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionETC2)) {
|
||||
requiredFeatures[cur_feature_index++] = WGPUFeatureName_TextureCompressionETC2;
|
||||
}
|
||||
|
||||
WGPUDeviceDescriptor dev_desc;
|
||||
_sapp_clear(&dev_desc, sizeof(dev_desc));
|
||||
dev_desc.requiredFeaturesCount = cur_feature_index;
|
||||
dev_desc.requiredFeatures = requiredFeatures,
|
||||
wgpuAdapterRequestDevice(adapter, &dev_desc, _sapp_emsc_wgpu_request_device_cb, 0);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_init(void) {
|
||||
SOKOL_ASSERT(0 == _sapp.wgpu.instance);
|
||||
SOKOL_ASSERT(!_sapp.wgpu.async_init_done);
|
||||
_sapp.wgpu.instance = wgpuCreateInstance(0);
|
||||
if (0 == _sapp.wgpu.instance) {
|
||||
_SAPP_PANIC(WGPU_CREATE_INSTANCE_FAILED);
|
||||
}
|
||||
// FIXME: power preference?
|
||||
wgpuInstanceRequestAdapter(_sapp.wgpu.instance, 0, _sapp_emsc_wgpu_request_adapter_cb, 0);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_wgpu_frame(void) {
|
||||
if (_sapp.wgpu.async_init_done) {
|
||||
_sapp.wgpu.swapchain_view = wgpuSwapChainGetCurrentTextureView(_sapp.wgpu.swapchain);
|
||||
_sapp_frame();
|
||||
wgpuTextureViewRelease(_sapp.wgpu.swapchain_view);
|
||||
_sapp.wgpu.swapchain_view = 0;
|
||||
}
|
||||
}
|
||||
#endif // SOKOL_WGPU
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) {
|
||||
emscripten_set_mousedown_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb);
|
||||
|
@ -5812,32 +5869,12 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) {
|
|||
_sapp_timing_external(&_sapp.timing, time / 1000.0);
|
||||
|
||||
#if defined(SOKOL_WGPU)
|
||||
/*
|
||||
on WebGPU, the emscripten frame callback will already be called while
|
||||
the asynchronous WebGPU device and swapchain initialization is still
|
||||
in progress
|
||||
*/
|
||||
switch (_sapp.emsc.wgpu.state) {
|
||||
case _SAPP_EMSC_WGPU_STATE_INITIAL:
|
||||
/* async JS init hasn't finished yet */
|
||||
break;
|
||||
case _SAPP_EMSC_WGPU_STATE_READY:
|
||||
/* perform post-async init stuff */
|
||||
_sapp_emsc_wgpu_surfaces_create();
|
||||
_sapp.emsc.wgpu.state = _SAPP_EMSC_WGPU_STATE_RUNNING;
|
||||
break;
|
||||
case _SAPP_EMSC_WGPU_STATE_RUNNING:
|
||||
/* a regular frame */
|
||||
_sapp_emsc_wgpu_next_frame();
|
||||
_sapp_frame();
|
||||
break;
|
||||
}
|
||||
_sapp_emsc_wgpu_frame();
|
||||
#else
|
||||
/* WebGL code path */
|
||||
_sapp_frame();
|
||||
#endif
|
||||
|
||||
/* quit-handling */
|
||||
// quit-handling
|
||||
if (_sapp.quit_requested) {
|
||||
_sapp_init_event(SAPP_EVENTTYPE_QUIT_REQUESTED);
|
||||
_sapp_call_event(&_sapp.event);
|
||||
|
@ -5877,18 +5914,17 @@ _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) {
|
|||
#if defined(SOKOL_GLES3)
|
||||
_sapp_emsc_webgl_init();
|
||||
#elif defined(SOKOL_WGPU)
|
||||
sapp_js_wgpu_init();
|
||||
_sapp_emsc_wgpu_init();
|
||||
#endif
|
||||
_sapp.valid = true;
|
||||
_sapp_emsc_register_eventhandlers();
|
||||
sapp_set_icon(&desc->icon);
|
||||
|
||||
/* start the frame loop */
|
||||
// start the frame loop
|
||||
emscripten_request_animation_frame_loop(_sapp_emsc_frame, 0);
|
||||
|
||||
/* NOT A BUG: do not call _sapp_discard_state() here, instead this is
|
||||
called in _sapp_emsc_frame() when the application is ordered to quit
|
||||
*/
|
||||
// NOT A BUG: do not call _sapp_discard_state() here, instead this is
|
||||
// called in _sapp_emsc_frame() when the application is ordered to quit
|
||||
}
|
||||
|
||||
#if !defined(SOKOL_NO_ENTRY)
|
||||
|
@ -5932,6 +5968,99 @@ _SOKOL_PRIVATE void _sapp_gl_init_fbconfig(_sapp_gl_fbconfig* fbconfig) {
|
|||
fbconfig->samples = -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int least_missing;
|
||||
int least_color_diff;
|
||||
int least_extra_diff;
|
||||
bool best_match;
|
||||
} _sapp_gl_fbselect;
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_gl_init_fbselect(_sapp_gl_fbselect* fbselect) {
|
||||
_sapp_clear(fbselect, sizeof(_sapp_gl_fbselect));
|
||||
fbselect->least_missing = 1000000;
|
||||
fbselect->least_color_diff = 10000000;
|
||||
fbselect->least_extra_diff = 10000000;
|
||||
fbselect->best_match = false;
|
||||
}
|
||||
|
||||
// NOTE: this is used only in the WGL code path
|
||||
_SOKOL_PRIVATE bool _sapp_gl_select_fbconfig(_sapp_gl_fbselect* fbselect, const _sapp_gl_fbconfig* desired, const _sapp_gl_fbconfig* current) {
|
||||
int missing = 0;
|
||||
if (desired->doublebuffer != current->doublebuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((desired->alpha_bits > 0) && (current->alpha_bits == 0)) {
|
||||
missing++;
|
||||
}
|
||||
if ((desired->depth_bits > 0) && (current->depth_bits == 0)) {
|
||||
missing++;
|
||||
}
|
||||
if ((desired->stencil_bits > 0) && (current->stencil_bits == 0)) {
|
||||
missing++;
|
||||
}
|
||||
if ((desired->samples > 0) && (current->samples == 0)) {
|
||||
/* Technically, several multisampling buffers could be
|
||||
involved, but that's a lower level implementation detail and
|
||||
not important to us here, so we count them as one
|
||||
*/
|
||||
missing++;
|
||||
}
|
||||
|
||||
/* These polynomials make many small channel size differences matter
|
||||
less than one large channel size difference
|
||||
Calculate color channel size difference value
|
||||
*/
|
||||
int color_diff = 0;
|
||||
if (desired->red_bits != -1) {
|
||||
color_diff += (desired->red_bits - current->red_bits) * (desired->red_bits - current->red_bits);
|
||||
}
|
||||
if (desired->green_bits != -1) {
|
||||
color_diff += (desired->green_bits - current->green_bits) * (desired->green_bits - current->green_bits);
|
||||
}
|
||||
if (desired->blue_bits != -1) {
|
||||
color_diff += (desired->blue_bits - current->blue_bits) * (desired->blue_bits - current->blue_bits);
|
||||
}
|
||||
|
||||
/* Calculate non-color channel size difference value */
|
||||
int extra_diff = 0;
|
||||
if (desired->alpha_bits != -1) {
|
||||
extra_diff += (desired->alpha_bits - current->alpha_bits) * (desired->alpha_bits - current->alpha_bits);
|
||||
}
|
||||
if (desired->depth_bits != -1) {
|
||||
extra_diff += (desired->depth_bits - current->depth_bits) * (desired->depth_bits - current->depth_bits);
|
||||
}
|
||||
if (desired->stencil_bits != -1) {
|
||||
extra_diff += (desired->stencil_bits - current->stencil_bits) * (desired->stencil_bits - current->stencil_bits);
|
||||
}
|
||||
if (desired->samples != -1) {
|
||||
extra_diff += (desired->samples - current->samples) * (desired->samples - current->samples);
|
||||
}
|
||||
|
||||
/* Figure out if the current one is better than the best one found so far
|
||||
Least number of missing buffers is the most important heuristic,
|
||||
then color buffer size match and lastly size match for other buffers
|
||||
*/
|
||||
bool new_closest = false;
|
||||
if (missing < fbselect->least_missing) {
|
||||
new_closest = true;
|
||||
} else if (missing == fbselect->least_missing) {
|
||||
if ((color_diff < fbselect->least_color_diff) ||
|
||||
((color_diff == fbselect->least_color_diff) && (extra_diff < fbselect->least_extra_diff)))
|
||||
{
|
||||
new_closest = true;
|
||||
}
|
||||
}
|
||||
if (new_closest) {
|
||||
fbselect->least_missing = missing;
|
||||
fbselect->least_color_diff = color_diff;
|
||||
fbselect->least_extra_diff = extra_diff;
|
||||
fbselect->best_match = (missing | color_diff | extra_diff) == 0;
|
||||
}
|
||||
return new_closest;
|
||||
}
|
||||
|
||||
// NOTE: this is used only in the GLX code path
|
||||
_SOKOL_PRIVATE const _sapp_gl_fbconfig* _sapp_gl_choose_fbconfig(const _sapp_gl_fbconfig* desired, const _sapp_gl_fbconfig* alternatives, int count) {
|
||||
int missing, least_missing = 1000000;
|
||||
int color_diff, least_color_diff = 10000000;
|
||||
|
@ -6609,44 +6738,55 @@ _SOKOL_PRIVATE int _sapp_wgl_attrib(int pixel_format, int attrib) {
|
|||
return value;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sapp_wgl_attribiv(int pixel_format, int num_attribs, const int* attribs, int* results) {
|
||||
SOKOL_ASSERT(_sapp.wgl.arb_pixel_format);
|
||||
if (!_sapp.wgl.GetPixelFormatAttribivARB(_sapp.win32.dc, pixel_format, 0, num_attribs, attribs, results)) {
|
||||
_SAPP_PANIC(WIN32_GET_PIXELFORMAT_ATTRIB_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE int _sapp_wgl_find_pixel_format(void) {
|
||||
SOKOL_ASSERT(_sapp.win32.dc);
|
||||
SOKOL_ASSERT(_sapp.wgl.arb_pixel_format);
|
||||
const _sapp_gl_fbconfig* closest;
|
||||
|
||||
#define _sapp_wgl_num_query_tags (12)
|
||||
const int query_tags[_sapp_wgl_num_query_tags] = {
|
||||
WGL_SUPPORT_OPENGL_ARB,
|
||||
WGL_DRAW_TO_WINDOW_ARB,
|
||||
WGL_PIXEL_TYPE_ARB,
|
||||
WGL_ACCELERATION_ARB,
|
||||
WGL_DOUBLE_BUFFER_ARB,
|
||||
WGL_RED_BITS_ARB,
|
||||
WGL_GREEN_BITS_ARB,
|
||||
WGL_BLUE_BITS_ARB,
|
||||
WGL_ALPHA_BITS_ARB,
|
||||
WGL_DEPTH_BITS_ARB,
|
||||
WGL_STENCIL_BITS_ARB,
|
||||
WGL_SAMPLES_ARB,
|
||||
};
|
||||
const int result_support_opengl_index = 0;
|
||||
const int result_draw_to_window_index = 1;
|
||||
const int result_pixel_type_index = 2;
|
||||
const int result_acceleration_index = 3;
|
||||
const int result_double_buffer_index = 4;
|
||||
const int result_red_bits_index = 5;
|
||||
const int result_green_bits_index = 6;
|
||||
const int result_blue_bits_index = 7;
|
||||
const int result_alpha_bits_index = 8;
|
||||
const int result_depth_bits_index = 9;
|
||||
const int result_stencil_bits_index = 10;
|
||||
const int result_samples_index = 11;
|
||||
|
||||
int query_results[_sapp_wgl_num_query_tags] = {0};
|
||||
// Drop the last item if multisample extension is not supported.
|
||||
// If in future querying with multiple extensions, will have to shuffle index values to have active extensions on the end.
|
||||
int query_count = _sapp_wgl_num_query_tags;
|
||||
if (!_sapp.wgl.arb_multisample) {
|
||||
query_count = _sapp_wgl_num_query_tags - 1;
|
||||
}
|
||||
|
||||
int native_count = _sapp_wgl_attrib(1, WGL_NUMBER_PIXEL_FORMATS_ARB);
|
||||
_sapp_gl_fbconfig* usable_configs = (_sapp_gl_fbconfig*) _sapp_malloc_clear((size_t)native_count * sizeof(_sapp_gl_fbconfig));
|
||||
SOKOL_ASSERT(usable_configs);
|
||||
int usable_count = 0;
|
||||
for (int i = 0; i < native_count; i++) {
|
||||
const int n = i + 1;
|
||||
_sapp_gl_fbconfig* u = usable_configs + usable_count;
|
||||
_sapp_gl_init_fbconfig(u);
|
||||
if (!_sapp_wgl_attrib(n, WGL_SUPPORT_OPENGL_ARB) || !_sapp_wgl_attrib(n, WGL_DRAW_TO_WINDOW_ARB)) {
|
||||
continue;
|
||||
}
|
||||
if (_sapp_wgl_attrib(n, WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB) {
|
||||
continue;
|
||||
}
|
||||
if (_sapp_wgl_attrib(n, WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB) {
|
||||
continue;
|
||||
}
|
||||
u->red_bits = _sapp_wgl_attrib(n, WGL_RED_BITS_ARB);
|
||||
u->green_bits = _sapp_wgl_attrib(n, WGL_GREEN_BITS_ARB);
|
||||
u->blue_bits = _sapp_wgl_attrib(n, WGL_BLUE_BITS_ARB);
|
||||
u->alpha_bits = _sapp_wgl_attrib(n, WGL_ALPHA_BITS_ARB);
|
||||
u->depth_bits = _sapp_wgl_attrib(n, WGL_DEPTH_BITS_ARB);
|
||||
u->stencil_bits = _sapp_wgl_attrib(n, WGL_STENCIL_BITS_ARB);
|
||||
if (_sapp_wgl_attrib(n, WGL_DOUBLE_BUFFER_ARB)) {
|
||||
u->doublebuffer = true;
|
||||
}
|
||||
if (_sapp.wgl.arb_multisample) {
|
||||
u->samples = _sapp_wgl_attrib(n, WGL_SAMPLES_ARB);
|
||||
}
|
||||
u->handle = (uintptr_t)n;
|
||||
usable_count++;
|
||||
}
|
||||
SOKOL_ASSERT(usable_count > 0);
|
||||
|
||||
_sapp_gl_fbconfig desired;
|
||||
_sapp_gl_init_fbconfig(&desired);
|
||||
desired.red_bits = 8;
|
||||
|
@ -6656,13 +6796,46 @@ _SOKOL_PRIVATE int _sapp_wgl_find_pixel_format(void) {
|
|||
desired.depth_bits = 24;
|
||||
desired.stencil_bits = 8;
|
||||
desired.doublebuffer = true;
|
||||
desired.samples = _sapp.sample_count > 1 ? _sapp.sample_count : 0;
|
||||
closest = _sapp_gl_choose_fbconfig(&desired, usable_configs, usable_count);
|
||||
desired.samples = (_sapp.sample_count > 1) ? _sapp.sample_count : 0;
|
||||
|
||||
int pixel_format = 0;
|
||||
if (closest) {
|
||||
pixel_format = (int) closest->handle;
|
||||
|
||||
_sapp_gl_fbselect fbselect;
|
||||
_sapp_gl_init_fbselect(&fbselect);
|
||||
for (int i = 0; i < native_count; i++) {
|
||||
const int n = i + 1;
|
||||
_sapp_wgl_attribiv(n, query_count, query_tags, query_results);
|
||||
|
||||
if (query_results[result_support_opengl_index] == 0
|
||||
|| query_results[result_draw_to_window_index] == 0
|
||||
|| query_results[result_pixel_type_index] != WGL_TYPE_RGBA_ARB
|
||||
|| query_results[result_acceleration_index] == WGL_NO_ACCELERATION_ARB)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_sapp_gl_fbconfig u;
|
||||
_sapp_clear(&u, sizeof(u));
|
||||
u.red_bits = query_results[result_red_bits_index];
|
||||
u.green_bits = query_results[result_green_bits_index];
|
||||
u.blue_bits = query_results[result_blue_bits_index];
|
||||
u.alpha_bits = query_results[result_alpha_bits_index];
|
||||
u.depth_bits = query_results[result_depth_bits_index];
|
||||
u.stencil_bits = query_results[result_stencil_bits_index];
|
||||
u.doublebuffer = 0 != query_results[result_double_buffer_index];
|
||||
u.samples = query_results[result_samples_index]; // NOTE: If arb_multisample is not supported - just takes the default 0
|
||||
|
||||
// Test if this pixel format is better than the previous one
|
||||
if (_sapp_gl_select_fbconfig(&fbselect, &desired, &u)) {
|
||||
pixel_format = (uintptr_t)n;
|
||||
|
||||
// Early exit if matching as good as possible
|
||||
if (fbselect.best_match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_sapp_free(usable_configs);
|
||||
|
||||
return pixel_format;
|
||||
}
|
||||
|
||||
|
@ -11074,7 +11247,7 @@ SOKOL_API_IMPL float sapp_heightf(void) {
|
|||
|
||||
SOKOL_API_IMPL int sapp_color_format(void) {
|
||||
#if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU)
|
||||
switch (_sapp.emsc.wgpu.render_format) {
|
||||
switch (_sapp.wgpu.render_format) {
|
||||
case WGPUTextureFormat_RGBA8Unorm:
|
||||
return _SAPP_PIXELFORMAT_RGBA8;
|
||||
case WGPUTextureFormat_BGRA8Unorm:
|
||||
|
@ -11502,7 +11675,7 @@ SOKOL_API_IMPL const void* sapp_win32_get_hwnd(void) {
|
|||
SOKOL_API_IMPL const void* sapp_wgpu_get_device(void) {
|
||||
SOKOL_ASSERT(_sapp.valid);
|
||||
#if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU)
|
||||
return (const void*) _sapp.emsc.wgpu.device;
|
||||
return (const void*) _sapp.wgpu.device;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -11512,10 +11685,10 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_render_view(void) {
|
|||
SOKOL_ASSERT(_sapp.valid);
|
||||
#if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU)
|
||||
if (_sapp.sample_count > 1) {
|
||||
return (const void*) _sapp.emsc.wgpu.msaa_view;
|
||||
return (const void*) _sapp.wgpu.msaa_view;
|
||||
}
|
||||
else {
|
||||
return (const void*) _sapp.emsc.wgpu.swapchain_view;
|
||||
return (const void*) _sapp.wgpu.swapchain_view;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
|
@ -11526,7 +11699,7 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_resolve_view(void) {
|
|||
SOKOL_ASSERT(_sapp.valid);
|
||||
#if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU)
|
||||
if (_sapp.sample_count > 1) {
|
||||
return (const void*) _sapp.emsc.wgpu.swapchain_view;
|
||||
return (const void*) _sapp.wgpu.swapchain_view;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
|
@ -11539,7 +11712,7 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_resolve_view(void) {
|
|||
SOKOL_API_IMPL const void* sapp_wgpu_get_depth_stencil_view(void) {
|
||||
SOKOL_ASSERT(_sapp.valid);
|
||||
#if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU)
|
||||
return (const void*) _sapp.emsc.wgpu.depth_stencil_view;
|
||||
return (const void*) _sapp.wgpu.depth_stencil_view;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
|
128
source/engine/thirdparty/sokol/sokol_args.h
vendored
128
source/engine/thirdparty/sokol/sokol_args.h
vendored
|
@ -35,11 +35,22 @@
|
|||
|
||||
When running as WebAssembly app, arguments are taken from the page URL:
|
||||
|
||||
https://floooh.github.io/tiny8bit/kc85.html?type=kc85_3&mod=m022&snapshot=kc85/jungle.kcc
|
||||
https://floooh.github.io/tiny8bit/kc85.html?type=kc85_3&mod=m022&snapshot=kc85/jungle.kcc
|
||||
|
||||
The same arguments provided to a command line app:
|
||||
|
||||
kc85 type=kc85_3 mod=m022 snapshot=kc85/jungle.kcc
|
||||
kc85 type=kc85_3 mod=m022 snapshot=kc85/jungle.kcc
|
||||
|
||||
You can also use standalone keys without value:
|
||||
|
||||
https://floooh.github.io/tiny8bit/kc85.html?bla&blub
|
||||
|
||||
On the command line:
|
||||
|
||||
kc85 bla blub
|
||||
|
||||
Such value-less keys are reported as the value being an empty string, but they
|
||||
can be tested with `sapp_exists("bla")` or `sapp_boolean("blub")`.
|
||||
|
||||
ARGUMENT FORMATTING
|
||||
===================
|
||||
|
@ -57,6 +68,12 @@
|
|||
|
||||
key=value
|
||||
|
||||
or
|
||||
|
||||
key
|
||||
|
||||
When a key has no value, the value will be assigned an empty string.
|
||||
|
||||
Key/value pairs are separated by 'whitespace', valid whitespace
|
||||
characters are space and tab.
|
||||
|
||||
|
@ -71,9 +88,6 @@
|
|||
|
||||
The 'key' string must be a simple string without escape sequences or whitespace.
|
||||
|
||||
Currently 'single keys' without values are not allowed, but may be
|
||||
in the future.
|
||||
|
||||
The 'value' string can be quoted, and quoted value strings can contain
|
||||
whitespace:
|
||||
|
||||
|
@ -123,7 +137,7 @@
|
|||
...
|
||||
}
|
||||
|
||||
// check if a key's value is "true", "yes" or "on"
|
||||
// check if a key's value is "true", "yes" or "on" or if this is a standalone key
|
||||
if (sargs_boolean("joystick_enabled")) {
|
||||
...
|
||||
}
|
||||
|
@ -183,23 +197,23 @@
|
|||
Return true between sargs_setup() and sargs_shutdown()
|
||||
|
||||
bool sargs_exists(const char* key)
|
||||
Test if a key arg exists.
|
||||
Test if an argument exists by its key name.
|
||||
|
||||
const char* sargs_value(const char* key)
|
||||
Return value associated with key. Returns an empty
|
||||
string ("") if the key doesn't exist.
|
||||
Return value associated with key. Returns an empty string ("") if the
|
||||
key doesn't exist, or if the key doesn't have a value.
|
||||
|
||||
const char* sargs_value_def(const char* key, const char* default)
|
||||
Return value associated with key, or the provided default
|
||||
value if the value doesn't exist.
|
||||
Return value associated with key, or the provided default value if the
|
||||
key doesn't exist, or this is a value-less key.
|
||||
|
||||
bool sargs_equals(const char* key, const char* val);
|
||||
Return true if the value associated with key matches
|
||||
the 'val' argument.
|
||||
|
||||
bool sargs_boolean(const char* key)
|
||||
Return true if the value string of 'key' is one
|
||||
of 'true', 'yes', 'on'.
|
||||
Return true if the value string of 'key' is one of 'true', 'yes', 'on',
|
||||
or this is a key without value.
|
||||
|
||||
int sargs_find(const char* key)
|
||||
Find argument by key name and return its index, or -1 if not found.
|
||||
|
@ -213,7 +227,7 @@
|
|||
|
||||
const char* sargs_value_at(int index)
|
||||
Return the value of argument at index. Returns empty string
|
||||
if index is outside range.
|
||||
if the key at index has no value, or the index is out-of-range.
|
||||
|
||||
|
||||
MEMORY ALLOCATION OVERRIDE
|
||||
|
@ -233,8 +247,8 @@
|
|||
sargs_setup(&(sargs_desc){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc = my_alloc,
|
||||
.free = my_free,
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
|
@ -302,12 +316,12 @@ extern "C" {
|
|||
|
||||
Used in sargs_desc to provide custom memory-alloc and -free functions
|
||||
to sokol_args.h. If memory management should be overridden, both the
|
||||
alloc and free function must be provided (e.g. it's not valid to
|
||||
alloc_fn and free_fn function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
typedef struct sargs_allocator {
|
||||
void* (*alloc)(size_t size, void* user_data);
|
||||
void (*free)(void* ptr, void* user_data);
|
||||
void* (*alloc_fn)(size_t size, void* user_data);
|
||||
void (*free_fn)(void* ptr, void* user_data);
|
||||
void* user_data;
|
||||
} sargs_allocator;
|
||||
|
||||
|
@ -327,13 +341,13 @@ SOKOL_ARGS_API_DECL void sargs_shutdown(void);
|
|||
SOKOL_ARGS_API_DECL bool sargs_isvalid(void);
|
||||
/* test if an argument exists by key name */
|
||||
SOKOL_ARGS_API_DECL bool sargs_exists(const char* key);
|
||||
/* get value by key name, return empty string if key doesn't exist */
|
||||
/* get value by key name, return empty string if key doesn't exist or an existing key has no value */
|
||||
SOKOL_ARGS_API_DECL const char* sargs_value(const char* key);
|
||||
/* get value by key name, return provided default if key doesn't exist */
|
||||
/* get value by key name, return provided default if key doesn't exist or has no value */
|
||||
SOKOL_ARGS_API_DECL const char* sargs_value_def(const char* key, const char* def);
|
||||
/* return true if val arg matches the value associated with key */
|
||||
SOKOL_ARGS_API_DECL bool sargs_equals(const char* key, const char* val);
|
||||
/* return true if key's value is "true", "yes" or "on" */
|
||||
/* return true if key's value is "true", "yes", "on" or an existing key has no value */
|
||||
SOKOL_ARGS_API_DECL bool sargs_boolean(const char* key);
|
||||
/* get index of arg by key name, return -1 if not exists */
|
||||
SOKOL_ARGS_API_DECL int sargs_find(const char* key);
|
||||
|
@ -433,10 +447,9 @@ _SOKOL_PRIVATE void _sargs_clear(void* ptr, size_t size) {
|
|||
_SOKOL_PRIVATE void* _sargs_malloc(size_t size) {
|
||||
SOKOL_ASSERT(size > 0);
|
||||
void* ptr;
|
||||
if (_sargs.allocator.alloc) {
|
||||
ptr = _sargs.allocator.alloc(size, _sargs.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_sargs.allocator.alloc_fn) {
|
||||
ptr = _sargs.allocator.alloc_fn(size, _sargs.allocator.user_data);
|
||||
} else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
SOKOL_ASSERT(ptr);
|
||||
|
@ -450,10 +463,9 @@ _SOKOL_PRIVATE void* _sargs_malloc_clear(size_t size) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_free(void* ptr) {
|
||||
if (_sargs.allocator.free) {
|
||||
_sargs.allocator.free(ptr, _sargs.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_sargs.allocator.free_fn) {
|
||||
_sargs.allocator.free_fn(ptr, _sargs.allocator.user_data);
|
||||
} else {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
@ -486,8 +498,8 @@ _SOKOL_PRIVATE bool _sargs_val_expected(void) {
|
|||
return 0 != (_sargs.parse_state & _SARGS_EXPECT_VAL);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_expect_sep(void) {
|
||||
_sargs.parse_state = _SARGS_EXPECT_SEP;
|
||||
_SOKOL_PRIVATE void _sargs_expect_sep_or_key(void) {
|
||||
_sargs.parse_state = _SARGS_EXPECT_SEP | _SARGS_EXPECT_KEY;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _sargs_any_expected(void) {
|
||||
|
@ -524,14 +536,17 @@ _SOKOL_PRIVATE bool _sargs_is_whitespace(char c) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_start_key(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
SOKOL_ASSERT((_sargs.num_args >= 0) && (_sargs.num_args < _sargs.max_args));
|
||||
_sargs.parse_state = _SARGS_PARSING_KEY;
|
||||
_sargs.args[_sargs.num_args].key = _sargs.buf_pos;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_key(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
SOKOL_ASSERT((_sargs.num_args >= 0) && (_sargs.num_args < _sargs.max_args));
|
||||
_sargs_putc(0);
|
||||
// declare val as empty string in case this is a key-only arg
|
||||
_sargs.args[_sargs.num_args].val = _sargs.buf_pos - 1;
|
||||
_sargs.num_args++;
|
||||
_sargs.parse_state = 0;
|
||||
}
|
||||
|
||||
|
@ -540,15 +555,13 @@ _SOKOL_PRIVATE bool _sargs_parsing_key(void) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_start_val(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
SOKOL_ASSERT((_sargs.num_args > 0) && (_sargs.num_args <= _sargs.max_args));
|
||||
_sargs.parse_state = _SARGS_PARSING_VAL;
|
||||
_sargs.args[_sargs.num_args].val = _sargs.buf_pos;
|
||||
_sargs.args[_sargs.num_args - 1].val = _sargs.buf_pos;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sargs_end_val(void) {
|
||||
SOKOL_ASSERT(_sargs.num_args < _sargs.max_args);
|
||||
_sargs_putc(0);
|
||||
_sargs.num_args++;
|
||||
_sargs.parse_state = 0;
|
||||
}
|
||||
|
||||
|
@ -596,7 +609,12 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) {
|
|||
if (_sargs_any_expected()) {
|
||||
if (!_sargs_is_whitespace(c)) {
|
||||
/* start of key, value or separator */
|
||||
if (_sargs_key_expected()) {
|
||||
if (_sargs_is_separator(c)) {
|
||||
/* skip separator and expect value */
|
||||
_sargs_expect_val();
|
||||
continue;
|
||||
}
|
||||
else if (_sargs_key_expected()) {
|
||||
/* start of new key */
|
||||
_sargs_start_key();
|
||||
}
|
||||
|
@ -608,13 +626,6 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) {
|
|||
}
|
||||
_sargs_start_val();
|
||||
}
|
||||
else {
|
||||
/* separator */
|
||||
if (_sargs_is_separator(c)) {
|
||||
_sargs_expect_val();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* skip white space */
|
||||
|
@ -629,7 +640,7 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) {
|
|||
_sargs_expect_val();
|
||||
}
|
||||
else {
|
||||
_sargs_expect_sep();
|
||||
_sargs_expect_sep_or_key();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -657,7 +668,7 @@ _SOKOL_PRIVATE bool _sargs_parse_carg(const char* src) {
|
|||
}
|
||||
if (_sargs_parsing_key()) {
|
||||
_sargs_end_key();
|
||||
_sargs_expect_sep();
|
||||
_sargs_expect_sep_or_key();
|
||||
}
|
||||
else if (_sargs_parsing_val() && !_sargs_in_quotes()) {
|
||||
_sargs_end_val();
|
||||
|
@ -823,7 +834,13 @@ SOKOL_API_IMPL const char* sargs_value_def(const char* key, const char* def) {
|
|||
SOKOL_ASSERT(_sargs.valid && key && def);
|
||||
int arg_index = sargs_find(key);
|
||||
if (-1 != arg_index) {
|
||||
return sargs_value_at(arg_index);
|
||||
const char* res = sargs_value_at(arg_index);
|
||||
SOKOL_ASSERT(res);
|
||||
if (res[0] == 0) {
|
||||
return def;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return def;
|
||||
|
@ -836,10 +853,15 @@ SOKOL_API_IMPL bool sargs_equals(const char* key, const char* val) {
|
|||
}
|
||||
|
||||
SOKOL_API_IMPL bool sargs_boolean(const char* key) {
|
||||
const char* val = sargs_value(key);
|
||||
return (0 == strcmp("true", val)) ||
|
||||
(0 == strcmp("yes", val)) ||
|
||||
(0 == strcmp("on", val));
|
||||
if (sargs_exists(key)) {
|
||||
const char* val = sargs_value(key);
|
||||
return (0 == strcmp("true", val)) ||
|
||||
(0 == strcmp("yes", val)) ||
|
||||
(0 == strcmp("on", val)) ||
|
||||
(0 == strcmp("", val));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SOKOL_ARGS_IMPL */
|
||||
|
|
31
source/engine/thirdparty/sokol/sokol_audio.h
vendored
31
source/engine/thirdparty/sokol/sokol_audio.h
vendored
|
@ -397,8 +397,8 @@
|
|||
saudio_setup(&(saudio_desc){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc = my_alloc,
|
||||
.free = my_free,
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
|
@ -575,12 +575,12 @@ typedef struct saudio_logger {
|
|||
|
||||
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 and free function must be provided (e.g. it's not valid to
|
||||
alloc_fn and free_fn function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
typedef struct saudio_allocator {
|
||||
void* (*alloc)(size_t size, void* user_data);
|
||||
void (*free)(void* ptr, void* user_data);
|
||||
void* (*alloc_fn)(size_t size, void* user_data);
|
||||
void (*free_fn)(void* ptr, void* user_data);
|
||||
void* user_data;
|
||||
} saudio_allocator;
|
||||
|
||||
|
@ -1146,10 +1146,9 @@ _SOKOL_PRIVATE void _saudio_clear(void* ptr, size_t size) {
|
|||
_SOKOL_PRIVATE void* _saudio_malloc(size_t size) {
|
||||
SOKOL_ASSERT(size > 0);
|
||||
void* ptr;
|
||||
if (_saudio.desc.allocator.alloc) {
|
||||
ptr = _saudio.desc.allocator.alloc(size, _saudio.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_saudio.desc.allocator.alloc_fn) {
|
||||
ptr = _saudio.desc.allocator.alloc_fn(size, _saudio.desc.allocator.user_data);
|
||||
} else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
if (0 == ptr) {
|
||||
|
@ -1165,10 +1164,9 @@ _SOKOL_PRIVATE void* _saudio_malloc_clear(size_t size) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _saudio_free(void* ptr) {
|
||||
if (_saudio.desc.allocator.free) {
|
||||
_saudio.desc.allocator.free(ptr, _saudio.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_saudio.desc.allocator.free_fn) {
|
||||
_saudio.desc.allocator.free_fn(ptr, _saudio.desc.allocator.user_data);
|
||||
} else {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
@ -1519,15 +1517,13 @@ _SOKOL_PRIVATE bool _saudio_alsa_backend_init(void) {
|
|||
_SAUDIO_ERROR(ALSA_PTHREAD_CREATE_FAILED);
|
||||
goto error;
|
||||
}
|
||||
snd_config_update_free_global();
|
||||
|
||||
return true;
|
||||
error:
|
||||
|
||||
if (_saudio.backend.device) {
|
||||
snd_pcm_close(_saudio.backend.device);
|
||||
_saudio.backend.device = 0;
|
||||
}
|
||||
snd_config_update_free_global();
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -1537,7 +1533,6 @@ _SOKOL_PRIVATE void _saudio_alsa_backend_shutdown(void) {
|
|||
pthread_join(_saudio.backend.thread, 0);
|
||||
snd_pcm_drain(_saudio.backend.device);
|
||||
snd_pcm_close(_saudio.backend.device);
|
||||
snd_config_update_free_global();
|
||||
_saudio_free(_saudio.backend.buffer);
|
||||
};
|
||||
|
||||
|
@ -2488,7 +2483,7 @@ void _saudio_backend_shutdown(void) {
|
|||
SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
|
||||
SOKOL_ASSERT(!_saudio.valid);
|
||||
SOKOL_ASSERT(desc);
|
||||
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
|
||||
SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
|
||||
_saudio_clear(&_saudio, sizeof(_saudio));
|
||||
_saudio.desc = *desc;
|
||||
_saudio.stream_cb = desc->stream_cb;
|
||||
|
|
46
source/engine/thirdparty/sokol/sokol_fetch.h
vendored
46
source/engine/thirdparty/sokol/sokol_fetch.h
vendored
|
@ -820,8 +820,8 @@
|
|||
sfetch_setup(&(sfetch_desc_t){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc = my_alloc,
|
||||
.free = my_free,
|
||||
.alloc_fn = my_alloc,
|
||||
.free_fn = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
|
@ -1024,8 +1024,8 @@ typedef struct sfetch_range_t {
|
|||
override one function but not the other).
|
||||
*/
|
||||
typedef struct sfetch_allocator_t {
|
||||
void* (*alloc)(size_t size, void* user_data);
|
||||
void (*free)(void* ptr, void* user_data);
|
||||
void* (*alloc_fn)(size_t size, void* user_data);
|
||||
void (*free_fn)(void* ptr, void* user_data);
|
||||
void* user_data;
|
||||
} sfetch_allocator_t;
|
||||
|
||||
|
@ -1424,10 +1424,9 @@ _SOKOL_PRIVATE void _sfetch_clear(void* ptr, size_t size) {
|
|||
_SOKOL_PRIVATE void* _sfetch_malloc_with_allocator(const sfetch_allocator_t* allocator, size_t size) {
|
||||
SOKOL_ASSERT(size > 0);
|
||||
void* ptr;
|
||||
if (allocator->alloc) {
|
||||
ptr = allocator->alloc(size, allocator->user_data);
|
||||
}
|
||||
else {
|
||||
if (allocator->alloc_fn) {
|
||||
ptr = allocator->alloc_fn(size, allocator->user_data);
|
||||
} else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
if (0 == ptr) {
|
||||
|
@ -1447,10 +1446,9 @@ _SOKOL_PRIVATE void* _sfetch_malloc_clear(size_t size) {
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sfetch_free(void* ptr) {
|
||||
if (_sfetch->desc.allocator.free) {
|
||||
_sfetch->desc.allocator.free(ptr, _sfetch->desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
if (_sfetch->desc.allocator.free_fn) {
|
||||
_sfetch->desc.allocator.free_fn(ptr, _sfetch->desc.allocator.user_data);
|
||||
} else {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
@ -2457,6 +2455,12 @@ _SOKOL_PRIVATE void _sfetch_invoke_response_callback(_sfetch_item_t* item) {
|
|||
item->callback(&response);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _sfetch_cancel_item(_sfetch_item_t* item) {
|
||||
item->state = _SFETCH_STATE_FAILED;
|
||||
item->user.finished = true;
|
||||
item->user.error_code = SFETCH_ERROR_CANCELLED;
|
||||
}
|
||||
|
||||
/* per-frame channel stuff: move requests in and out of the IO threads, call response callbacks */
|
||||
_SOKOL_PRIVATE void _sfetch_channel_dowork(_sfetch_channel_t* chn, _sfetch_pool_t* pool) {
|
||||
|
||||
|
@ -2469,9 +2473,16 @@ _SOKOL_PRIVATE void _sfetch_channel_dowork(_sfetch_channel_t* chn, _sfetch_pool_
|
|||
_sfetch_item_t* item = _sfetch_pool_item_lookup(pool, slot_id);
|
||||
SOKOL_ASSERT(item);
|
||||
SOKOL_ASSERT(item->state == _SFETCH_STATE_ALLOCATED);
|
||||
// if the item was cancelled early, kick it out immediately
|
||||
if (item->user.cancel) {
|
||||
_sfetch_cancel_item(item);
|
||||
_sfetch_invoke_response_callback(item);
|
||||
_sfetch_pool_item_free(pool, slot_id);
|
||||
continue;
|
||||
}
|
||||
item->state = _SFETCH_STATE_DISPATCHED;
|
||||
item->lane = _sfetch_ring_dequeue(&chn->free_lanes);
|
||||
/* if no buffer provided yet, invoke response callback to do so */
|
||||
// if no buffer provided yet, invoke response callback to do so
|
||||
if (0 == item->buffer.ptr) {
|
||||
_sfetch_invoke_response_callback(item);
|
||||
}
|
||||
|
@ -2498,8 +2509,7 @@ _SOKOL_PRIVATE void _sfetch_channel_dowork(_sfetch_channel_t* chn, _sfetch_pool_
|
|||
item->user.cont = false;
|
||||
}
|
||||
if (item->user.cancel) {
|
||||
item->state = _SFETCH_STATE_FAILED;
|
||||
item->user.finished = true;
|
||||
_sfetch_cancel_item(item);
|
||||
}
|
||||
switch (item->state) {
|
||||
case _SFETCH_STATE_DISPATCHED:
|
||||
|
@ -2541,7 +2551,7 @@ _SOKOL_PRIVATE void _sfetch_channel_dowork(_sfetch_channel_t* chn, _sfetch_pool_
|
|||
item->user.fetched_offset = item->thread.fetched_offset;
|
||||
item->user.fetched_size = item->thread.fetched_size;
|
||||
if (item->user.cancel) {
|
||||
item->user.error_code = SFETCH_ERROR_CANCELLED;
|
||||
_sfetch_cancel_item(item);
|
||||
}
|
||||
else {
|
||||
item->user.error_code = item->thread.error_code;
|
||||
|
@ -2558,7 +2568,7 @@ _SOKOL_PRIVATE void _sfetch_channel_dowork(_sfetch_channel_t* chn, _sfetch_pool_
|
|||
}
|
||||
_sfetch_invoke_response_callback(item);
|
||||
|
||||
/* when the request is finish, free the lane for another request,
|
||||
/* when the request is finished, free the lane for another request,
|
||||
otherwise feed it back into the incoming queue
|
||||
*/
|
||||
if (item->user.finished) {
|
||||
|
@ -2608,7 +2618,7 @@ _SOKOL_PRIVATE bool _sfetch_validate_request(_sfetch_t* ctx, const sfetch_reques
|
|||
}
|
||||
|
||||
_SOKOL_PRIVATE sfetch_desc_t _sfetch_desc_defaults(const sfetch_desc_t* desc) {
|
||||
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
|
||||
SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
|
||||
sfetch_desc_t res = *desc;
|
||||
res.max_requests = _sfetch_def(desc->max_requests, 128);
|
||||
res.num_channels = _sfetch_def(desc->num_channels, 1);
|
||||
|
|
4673
source/engine/thirdparty/sokol/sokol_gfx.h
vendored
4673
source/engine/thirdparty/sokol/sokol_gfx.h
vendored
File diff suppressed because it is too large
Load diff
|
@ -27,8 +27,8 @@
|
|||
sg_setup(&(sg_desc){
|
||||
//...
|
||||
.allocator = {
|
||||
.alloc = smemtrack_alloc,
|
||||
.free = smemtrack_free,
|
||||
.alloc_fn = smemtrack_alloc,
|
||||
.free_fn = smemtrack_free,
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue