fix rendering

This commit is contained in:
John Alanbrook 2024-09-29 06:10:42 -05:00
parent 9bbe880466
commit 6b94349a64
18 changed files with 304 additions and 80 deletions

View file

@ -77,7 +77,7 @@ endif
CXXFLAGS += -std=c++14 CXXFLAGS += -std=c++14
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DDATE=\"$(DATE)\" -DINFO=\"$(INFO)\" -Wno-narrowing #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DDATE=\"$(DATE)\" -DINFO=\"$(INFO)\" -Wno-narrowing -Wno-int-conversion #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t
CPPFLAGS += -DCONFIG_VERSION=\"2024-02-14\" -DCONFIG_BIGNUM #for quickjs CPPFLAGS += -DCONFIG_VERSION=\"2024-02-14\" -DCONFIG_BIGNUM #for quickjs
# ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER # ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER

View file

@ -1209,6 +1209,11 @@ Math.mean = vector.mean;
Math.sigma = vector.sigma; Math.sigma = vector.sigma;
Math.median = vector.median; Math.median = vector.median;
vector.v2one = [1,1];
vector.v3one = [1,1,1];
vector.v2zero = [0,0];
vector.v3zero = [0,0,0];
Math.variance = function (series) { Math.variance = function (series) {
var mean = Math.mean(series); var mean = Math.mean(series);
var vnce = 0; var vnce = 0;

View file

@ -332,12 +332,41 @@ profile.curframe = 0;
profile.snapshot = {}; profile.snapshot = {};
var fps = []; var fps = [];
var frame_lead = 240;
var classes = ["gameobject", "transform", "dsp_node", "texture", "font", "warp_gravity", "warp_damp", "sg_buffer", "datastream", "cpShape", "cpConstraint", "timer", "skin"];
var get_snapshot = function()
{
var snap = profile.snapshot;
snap.actors ??= {};
Object.assign(snap.actors, actor.__stats());
snap.memory ??= {};
Object.assign(snap.memory, os.mem());
snap.memory.textures = game.texture.total_size();
snap.memory.texture_vram = game.texture.total_vram();
snap.rusage ??= {};
var rusage = os.rusage();
rusage.ru_maxrss *= 1024; // delivered in KB; convert here to B
Object.assign(snap.rusage, rusage);
snap.mallinfo ??= {};
Object.assign(snap.mallinfo, os.mallinfo());
snap.obj ??= {};
for (var i of classes) {
var proto = globalThis[`${i}_proto`];
if (!proto) continue;
snap.obj[i] = proto._count();
}
}
profile.report_frame = function (t) { profile.report_frame = function (t) {
fps.push(t); fps.push(t);
if (fps.length > 15) { if (fps.length > frame_lead) {
profile.snapshot.fps = Math.mean(fps); profile.snapshot.fps = Math.mean(fps);
fps = []; fps.length = 0;
get_snapshot();
} }
}; };

View file

@ -193,7 +193,7 @@ game.tex_hotreload = function () {
}; };
game.texture = function (path) { game.texture = function (path) {
if (!path) return game.texture("icons/no_text.gif"); if (!path) return game.texture("icons/no_tex.gif");
path = Resources.find_image(path); path = Resources.find_image(path);
if (!io.exists(path)) { if (!io.exists(path)) {
@ -210,6 +210,20 @@ game.texture = function (path) {
game.texture.cache = {}; game.texture.cache = {};
game.texture.time_cache = {}; game.texture.time_cache = {};
game.texture.total_size = function()
{
var size = 0;
Object.values(game.texture.cache).forEach(x => size += x.inram() ? x.width*x.height*4 : 0);
return size;
}
game.texture.total_vram = function()
{
var vram = 0;
Object.values(game.texture.cache).forEach(x => vram += x.vram);
return vram;
}
prosperon.semver = {}; prosperon.semver = {};
prosperon.semver.valid = function (v, range) { prosperon.semver.valid = function (v, range) {
v = v.split("."); v = v.split(".");

View file

@ -533,11 +533,9 @@ render.sprites = function render_sprites() {
var sparray = layer[img]; var sparray = layer[img];
if (sparray.length === 0) continue; if (sparray.length === 0) continue;
var ss = sparray[0]; var ss = sparray[0];
// render.use_mat(ss); ss.baseinstance = render.make_sprite_ssbo(sparray, sprite_ssbo);
cur.images = [ss.diffuse]; render.use_mat(ss);
render.make_sprite_ssbo(sparray, sprite_ssbo);
render.draw(shape.quad, sprite_ssbo, sparray.length); render.draw(shape.quad, sprite_ssbo, sparray.length);
if (debug.sprite_nums) render.text(ss.diffuse.getid(), ss.transform.pos);
} }
} }
profile.endframe(); profile.endframe();
@ -586,6 +584,10 @@ function check_flush(flush_fn) {
} }
render.flush = check_flush; render.flush = check_flush;
render.forceflush = function()
{
if (nextflush) nextflush();
}
var poly_cache = []; var poly_cache = [];
var poly_idx = 0; var poly_idx = 0;
@ -610,14 +612,12 @@ function poly_e() {
function flush_poly() { function flush_poly() {
if (poly_idx === 0) return; if (poly_idx === 0) return;
render.use_shader(polyssboshader); render.use_shader(polyssboshader);
render.use_mat({}); var base = render.make_particle_ssbo(poly_cache.slice(0, poly_idx), poly_ssbo);
render.make_particle_ssbo(poly_cache.slice(0, poly_idx), poly_ssbo); render.use_mat({baseinstance:base});
render.draw(shape.centered_quad, poly_ssbo, poly_idx); render.draw(shape.centered_quad, poly_ssbo, poly_idx);
poly_idx = 0; poly_idx = 0;
} }
function flush_image() {}
render.line = function render_line(points, color = Color.white, thickness = 1) { render.line = function render_line(points, color = Color.white, thickness = 1) {
for (var i = 0; i < points.length - 1; i++) { for (var i = 0; i < points.length - 1; i++) {
var a = points[i]; var a = points[i];
@ -719,10 +719,10 @@ var img_idx = 0;
function flush_img() { function flush_img() {
if (img_idx === 0) return; if (img_idx === 0) return;
render.use_shader(spritessboshader); render.use_shader(spritessboshader);
//render.use_mat({ diffuse: lasttex }); var startidx = render.make_sprite_ssbo(img_cache.slice(0, img_idx), sprite_ssbo);
render.make_sprite_ssbo(img_cache.slice(0, img_idx), poly_ssbo); render.use_mat({ baseinstance:startidx});
cur.images = [lasttex]; cur.images = [lasttex];
render.draw(shape.quad, poly_ssbo, img_idx); render.draw(shape.quad, sprite_ssbo, img_idx);
lasttex = undefined; lasttex = undefined;
img_idx = 0; img_idx = 0;
} }
@ -745,8 +745,11 @@ render.image = function image(tex, pos, scale, rotation = 0, color = Color.white
if (typeof tex === "string") if (typeof tex === "string")
tex = game.texture(tex); tex = game.texture(tex);
scale ??= [tex.width,tex.height]; if (scale)
scale = scale.div([tex.width, tex.height]);
else
scale = vector.v3one;
if (!tex) return; if (!tex) return;
if (!lasttex) { if (!lasttex) {
@ -763,7 +766,7 @@ render.image = function image(tex, pos, scale, rotation = 0, color = Color.white
e.transform.trs(pos, undefined, scale); e.transform.trs(pos, undefined, scale);
e.shade = color; e.shade = color;
e.texture = tex; e.texture = tex;
return; return;
var bb = {}; var bb = {};
bb.b = pos.y; bb.b = pos.y;
@ -1035,6 +1038,7 @@ prosperon.render = function () {
profile.endframe(); profile.endframe();
profile.frame("draws"); profile.frame("draws");
prosperon.draw(); prosperon.draw();
// sgl.draw();
profile.endframe(); profile.endframe();
prosperon.hudcam.size = prosperon.camera.size; prosperon.hudcam.size = prosperon.camera.size;
prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x / 2, prosperon.hudcam.size.y / 2, -100]; prosperon.hudcam.transform.pos = [prosperon.hudcam.size.x / 2, prosperon.hudcam.size.y / 2, -100];
@ -1095,9 +1099,8 @@ prosperon.render = function () {
render.end_pass(); render.end_pass();
profile.report_frame(profile.secs(profile.now()) - frame_t);
render.commit(); render.commit();
profile.report_frame(profile.secs(profile.now()) - frame_t);
endframe(); endframe();
}; };

View file

@ -17,8 +17,10 @@ readonly buffer ssbo {
poly polys[]; poly polys[];
}; };
uniform float baseinstance;
void main() { void main() {
poly p = polys[gl_InstanceIndex]; poly p = polys[int(baseinstance)+gl_InstanceIndex];
gl_Position = vp * p.model * vec4(a_pos, 1); gl_Position = vp * p.model * vec4(a_pos, 1);
shade = p.color; shade = p.color;
} }

View file

@ -22,10 +22,11 @@ readonly buffer ssbo {
}; };
uniform mat4 vp; uniform mat4 vp;
uniform float baseinstance;
void main() void main()
{ {
sprite s = sprites[gl_InstanceIndex]; sprite s = sprites[int(baseinstance)+gl_InstanceIndex];
pos = a_pos; pos = a_pos;
uv = a_uv; uv = a_uv;
pos *= vec3(s.rect.zw,1); pos *= vec3(s.rect.zw,1);

View file

@ -195,6 +195,9 @@
#define FMT_VEC4 "[%g,%g,%g,%g]" #define FMT_VEC4 "[%g,%g,%g,%g]"
#define PRINT_VEC4(vec) vec.x, vec.y, vec.z, vec.w #define PRINT_VEC4(vec) vec.x, vec.y, vec.z, vec.w
#define FMT_M4 "[%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g\n%g,%g,%g,%g]"
#define PRINT_M4(m) m.e[0][0], m.e[0][1], m.e[0][2], m.e[0][3], m.e[1][0], m.e[1][1], m.e[1][2], m.e[1][3], m.e[2][0], m.e[2][1], m.e[2][2], m.e[2][3], m.e[3][0], m.e[3][1], m.e[3][2], m.e[3][3]
typedef union HMM_Vec2 { typedef union HMM_Vec2 {
struct struct
{ {
@ -383,6 +386,8 @@ typedef union HMM_Vec4 {
HMM_Quat quat; HMM_Quat quat;
struct {float x, y, z, w; }; struct {float x, y, z, w; };
struct {float r, g, b, a; };
struct {float u0, u1, v0, v1;};
float Elements[4]; float Elements[4];
float e[4]; float e[4];

View file

@ -32,11 +32,15 @@
#include "par/par_streamlines.h" #include "par/par_streamlines.h"
#include "par/par_shapes.h" #include "par/par_shapes.h"
#include "sokol_glue.h" #include "sokol_glue.h"
#define SOKOL_GL_IMPL
#include "sokol/util/sokol_gl.h"
#include <chipmunk/chipmunk_unsafe.h> #include <chipmunk/chipmunk_unsafe.h>
#include <chipmunk/chipmunk_structs.h> #include <chipmunk/chipmunk_structs.h>
#include <stdint.h> #include <stdint.h>
#include "gui.h" #include "gui.h"
#include "timer.h" #include "timer.h"
#include <sys/resource.h>
#include <malloc.h>
#if (defined(_WIN32) || defined(__WIN32__)) #if (defined(_WIN32) || defined(__WIN32__))
#include <direct.h> #include <direct.h>
@ -45,9 +49,6 @@
static JSValue globalThis; static JSValue globalThis;
static JSClassID js_ptr_id;
static JSClassDef js_ptr_class = { "POINTER" };
JSValue str2js(const char *c, ...) { JSValue str2js(const char *c, ...) {
if (!c) return JS_UNDEFINED; if (!c) return JS_UNDEFINED;
char *result = NULL; char *result = NULL;
@ -69,7 +70,7 @@ const char *js2str(JSValue v) {
} }
char *js2strdup(JSValue v) { char *js2strdup(JSValue v) {
char *str = JS_ToCString(js, v); const char *str = JS_ToCString(js, v);
char *ret = strdup(str); char *ret = strdup(str);
JS_FreeCString(js, str); JS_FreeCString(js, str);
return ret; return ret;
@ -228,14 +229,6 @@ double js2angle(JSValue v) {
return n * HMM_TurnToRad; return n * HMM_TurnToRad;
} }
void *js2ptr(JSValue v) { return JS_GetOpaque(v,js_ptr_id); }
JSValue ptr2js(void *ptr) {
JSValue obj = JS_NewObjectClass(js, js_ptr_id);
JS_SetOpaque(obj, ptr);
return obj;
}
int js_arrlen(JSValue v) { int js_arrlen(JSValue v) {
if (JS_IsUndefined(v)) return 0; if (JS_IsUndefined(v)) return 0;
int len; int len;
@ -302,7 +295,7 @@ char *js_do_nota_decode(JSValue *tmp, char *nota)
char *js_do_nota_encode(JSValue v, char *nota) char *js_do_nota_encode(JSValue v, char *nota)
{ {
int tag = JS_VALUE_GET_TAG(v); int tag = JS_VALUE_GET_TAG(v);
char *str = NULL; const char *str = NULL;
JSPropertyEnum *ptab; JSPropertyEnum *ptab;
uint32_t plen; uint32_t plen;
int n; int n;
@ -764,7 +757,10 @@ JSC_CCALL(render_glue_pass,
) )
// Set the portion of the window to be rendered to // Set the portion of the window to be rendered to
JSC_CCALL(render_viewport, sg_apply_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0)) JSC_CCALL(render_viewport,
sg_apply_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
// sgl_viewportf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
)
JSC_CCALL(render_commit, sg_commit()) JSC_CCALL(render_commit, sg_commit())
JSC_CCALL(render_end_pass, sg_end_pass()) JSC_CCALL(render_end_pass, sg_end_pass())
@ -841,12 +837,12 @@ sg_shader js2shader(JSValue v)
desc.label = js2strdup(js_getpropstr(v, "name")); desc.label = js2strdup(js_getpropstr(v, "name"));
JSValue vs = js_getpropstr(prog, "vs"); JSValue vs = js_getpropstr(prog, "vs");
JSValue fs = js_getpropstr(prog, "fs"); JSValue fs = js_getpropstr(prog, "fs");
char *vsf = js2str(js_getpropstr(vs, "code")); const char *vsf = js2str(js_getpropstr(vs, "code"));
char *fsf = js2str(js_getpropstr(fs, "code")); const char *fsf = js2str(js_getpropstr(fs, "code"));
desc.vs.source = vsf; desc.vs.source = vsf;
desc.fs.source = fsf; desc.fs.source = fsf;
char *vsmain = js2str(js_getpropstr(vs, "entry_point")); const char *vsmain = js2str(js_getpropstr(vs, "entry_point"));
char *fsmain = js2str(js_getpropstr(fs, "entry_point")); const char *fsmain = js2str(js_getpropstr(fs, "entry_point"));
desc.vs.entry = vsmain; desc.vs.entry = vsmain;
desc.fs.entry = fsmain; desc.fs.entry = fsmain;
desc.vs.d3d11_target = "vs_4_0"; desc.vs.d3d11_target = "vs_4_0";
@ -994,6 +990,7 @@ JSC_CCALL(render_setuniv3,
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(f.e)); sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(f.e));
) )
JSC_CCALL(render_setuniv4, JSC_CCALL(render_setuniv4,
HMM_Vec4 v = {0}; HMM_Vec4 v = {0};
if (JS_IsArray(js, argv[2])) { if (JS_IsArray(js, argv[2])) {
@ -1059,10 +1056,12 @@ JSC_CCALL(render_make_particle_ssbo,
particle_ss ms[js_arrlen(array)]; particle_ss ms[js_arrlen(array)];
if (sg_query_buffer_will_overflow(*b, size)) { if (sg_query_buffer_will_overflow(*b, size)) {
sg_buffer_desc desc = sg_query_buffer_desc(*b);
sg_destroy_buffer(*b); sg_destroy_buffer(*b);
*b = sg_make_buffer(&(sg_buffer_desc){ *b = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_STORAGEBUFFER, .type = SG_BUFFERTYPE_STORAGEBUFFER,
.size = size, .size = size+desc.size,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "transform buffer" .label = "transform buffer"
}); });
@ -1074,10 +1073,12 @@ JSC_CCALL(render_make_particle_ssbo,
ms[i].color = js2vec4(js_getpropstr(sub,"color")); ms[i].color = js2vec4(js_getpropstr(sub,"color"));
} }
sg_append_buffer(*b, (&(sg_range){ int offset = sg_append_buffer(*b, (&(sg_range){
.ptr = ms, .ptr = ms,
.size = size .size = size
})); }));
ret = number2js(offset/sizeof(particle_ss));
) )
typedef struct sprite_ss { typedef struct sprite_ss {
@ -1095,10 +1096,11 @@ JSC_CCALL(render_make_sprite_ssbo,
sprite_ss ms[js_arrlen(array)]; sprite_ss ms[js_arrlen(array)];
if (sg_query_buffer_will_overflow(*b, size)) { if (sg_query_buffer_will_overflow(*b, size)) {
sg_buffer_desc desc = sg_query_buffer_desc(*b);
sg_destroy_buffer(*b); sg_destroy_buffer(*b);
*b = sg_make_buffer(&(sg_buffer_desc){ *b = sg_make_buffer(&(sg_buffer_desc){
.type = SG_BUFFERTYPE_STORAGEBUFFER, .type = SG_BUFFERTYPE_STORAGEBUFFER,
.size = size, .size = size+desc.size,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
.label = "transform buffer" .label = "transform buffer"
}); });
@ -1117,14 +1119,8 @@ JSC_CCALL(render_make_sprite_ssbo,
tscale.z = 1; tscale.z = 1;
tr->scale = HMM_MulV3(tr->scale, tscale); tr->scale = HMM_MulV3(tr->scale, tscale);
} }
tr->scale.x = 100; ms[i].model = transform2mat(tr);
tr->scale.y = 100;
tr->scale.z = 1;
tr->pos.x = 100;
tr->pos.y = 100;
tr->pos.z = 0;
ms[i].model = transform2mat(t);
ms[i].rect = js2vec4(js_getpropstr(sub,"rect")); ms[i].rect = js2vec4(js_getpropstr(sub,"rect"));
ms[i].shade = js2vec4(js_getpropstr(sub,"shade")); ms[i].shade = js2vec4(js_getpropstr(sub,"shade"));
@ -1132,10 +1128,12 @@ JSC_CCALL(render_make_sprite_ssbo,
tr->scale = HMM_DivV3(tr->scale, tscale); tr->scale = HMM_DivV3(tr->scale, tscale);
} }
sg_append_buffer(*b, (&(sg_range){ int offset = sg_append_buffer(*b, (&(sg_range){
.ptr = ms, .ptr = ms,
.size = size .size = size
})); }));
ret = number2js(offset/96);
) )
JSC_CCALL(render_make_t_ssbo, JSC_CCALL(render_make_t_ssbo,
@ -1218,7 +1216,107 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, make_sprite_ssbo, 2) MIST_FUNC_DEF(render, make_sprite_ssbo, 2)
}; };
JSC_CCALL(gui_scissor, sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0)) JSC_DCALL(sgl_enable_texture)
JSC_DCALL(sgl_disable_texture)
JSC_CCALL(sgl_texture, sgl_texture(js2texture(argv[0])->id, std_sampler))
JSC_DCALL(sgl_matrix_mode_modelview)
JSC_DCALL(sgl_matrix_mode_projection)
JSC_DCALL(sgl_matrix_mode_texture)
JSC_DCALL(sgl_load_identity)
JSC_CCALL(sgl_translate,
HMM_Vec3 v = js2vec3(argv[0]);
sgl_translate(v.x,v.y,v.z);
)
JSC_CCALL(sgl_rotate,
float rad = js2angle(argv[0]);
HMM_Vec3 axis = js2vec3(argv[1]);
sgl_rotate(rad, axis.x, axis.y, axis.z);
)
JSC_CCALL(sgl_scale,
HMM_Vec3 v = js2vec3(argv[0]);
sgl_scale(v.x, v.y, v.z);
)
JSC_CCALL(sgl_load_matrix,
transform *t = js2transform(argv[0]);
sgl_load_matrix(t->cache.e);
)
JSC_6CALL(sgl_frustum)
JSC_6CALL(sgl_ortho)
JSC_4CALL(sgl_perspective)
JSC_DCALL(sgl_push_matrix)
JSC_DCALL(sgl_pop_matrix)
JSC_1CALL(sgl_point_size)
JSC_DCALL(sgl_begin_points)
JSC_DCALL(sgl_begin_lines)
JSC_DCALL(sgl_begin_line_strip)
JSC_DCALL(sgl_begin_triangles)
JSC_DCALL(sgl_begin_triangle_strip)
JSC_DCALL(sgl_begin_quads)
JSC_DCALL(sgl_end)
JSC_DCALL(sgl_draw)
JSC_1CALL(sgl_layer)
JSC_1CALL(sgl_draw_layer)
JSC_CCALL(sgl_image,
texture *t = js2texture(argv[0]);
// transform *tr = js2transform(argv[1]);
HMM_Vec4 rect = js2vec4(argv[2]);
HMM_Vec4 color = js2vec4(argv[3]);
sgl_begin_quads();
sgl_c4f(color.r, color.g, color.b, color.a);
sgl_v2f(0,0);
sgl_v2f(0,1);
sgl_v2f(1,1);
sgl_v2f(1,0);
sgl_end();
// sgl_defaults();
)
JSC_CCALL(sgl_image_array,
JSValue array = argv[0];
sgl_begin_quads();
for (int i = 0; i < js_arrlen(array); i++) {
sgl_v2f(0,0);
sgl_v2f(0,1);
sgl_v2f(1,1);
sgl_v2f(1,0);
}
sgl_end();
)
static const JSCFunctionListEntry js_sgl_funcs[] = {
MIST_FUNC_DEF(sgl, enable_texture, 0),
MIST_FUNC_DEF(sgl, disable_texture, 0),
MIST_FUNC_DEF(sgl, texture, 1),
MIST_FUNC_DEF(sgl, matrix_mode_modelview, 0),
MIST_FUNC_DEF(sgl, matrix_mode_projection, 0),
MIST_FUNC_DEF(sgl, matrix_mode_texture, 0),
MIST_FUNC_DEF(sgl, load_identity, 0),
MIST_FUNC_DEF(sgl, translate, 1),
MIST_FUNC_DEF(sgl, rotate, 2),
MIST_FUNC_DEF(sgl, scale, 1),
MIST_FUNC_DEF(sgl, load_matrix, 1),
MIST_FUNC_DEF(sgl, frustum, 6),
MIST_FUNC_DEF(sgl, ortho, 6),
MIST_FUNC_DEF(sgl, perspective, 4),
MIST_FUNC_DEF(sgl, push_matrix, 0),
MIST_FUNC_DEF(sgl, pop_matrix, 0),
MIST_FUNC_DEF(sgl, point_size, 1),
MIST_FUNC_DEF(sgl, draw, 0),
MIST_FUNC_DEF(sgl, layer, 1),
MIST_FUNC_DEF(sgl, draw_layer, 1),
MIST_FUNC_DEF(sgl, image, 4),
MIST_FUNC_DEF(sgl, image_array, 1),
};
JSC_CCALL(gui_scissor,
sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
// sgl_scissor_rectf(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0);
)
JSC_CCALL(gui_text, JSC_CCALL(gui_text,
const char *s = JS_ToCString(js, argv[0]); const char *s = JS_ToCString(js, argv[0]);
HMM_Vec2 pos = js2vec2(argv[1]); HMM_Vec2 pos = js2vec2(argv[1]);
@ -1422,12 +1520,12 @@ JSC_CCALL(vector_clamp,
JSC_SSCALL(vector_trimchr, JSC_SSCALL(vector_trimchr,
int len = js2number(js_getpropstr(argv[0], "length")); int len = js2number(js_getpropstr(argv[0], "length"));
char *start = str; const char *start = str;
while (*start == *str2) while (*start == *str2)
start++; start++;
char *end = str + len-1; const char *end = str + len-1;
while(*end == *str2) while(*end == *str2)
end--; end--;
@ -1656,6 +1754,9 @@ static const JSCFunctionListEntry js_prosperon_funcs[] = {
MIST_FUNC_DEF(prosperon, guid, 0), MIST_FUNC_DEF(prosperon, guid, 0),
}; };
static const JSCFunctionListEntry js_sg_buffer_funcs[] = {
};
JSC_CCALL(time_now, JSC_CCALL(time_now,
struct timeval ct; struct timeval ct;
gettimeofday(&ct, NULL); gettimeofday(&ct, NULL);
@ -1760,7 +1861,7 @@ JSC_SCALL(io_mkdir, ret = number2js(mkdir(str,0777)))
JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv)
{ {
char *f = js2str(argv[0]); const char *f = js2str(argv[0]);
size_t len; size_t len;
unsigned char *d = slurp_file(f,&len); unsigned char *d = slurp_file(f,&len);
if (!d) { if (!d) {
@ -1776,7 +1877,7 @@ JSValue js_io_slurpbytes(JSContext *js, JSValue self, int argc, JSValue *argv)
JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv)
{ {
char *f = js2str(argv[0]); const char *f = js2str(argv[0]);
size_t len; size_t len;
char *s = slurp_text(f,&len); char *s = slurp_text(f,&len);
@ -1791,11 +1892,11 @@ JSValue js_io_slurp(JSContext *js, JSValue self, int argc, JSValue *argv)
JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv)
{ {
char *f = js2str(argv[0]); const char *f = js2str(argv[0]);
size_t len; size_t len;
JSValue ret; JSValue ret;
if (JS_IsString(argv[1])) { if (JS_IsString(argv[1])) {
char *data = JS_ToCStringLen(js, &len, argv[1]); const char *data = JS_ToCStringLen(js, &len, argv[1]);
ret = number2js(slurp_write(data, f, len)); ret = number2js(slurp_write(data, f, len));
JS_FreeCString(js,data); JS_FreeCString(js,data);
} else { } else {
@ -1808,7 +1909,7 @@ JSValue js_io_slurpwrite(JSContext *js, JSValue self, int argc, JSValue *argv)
JSValue js_io_chmod(JSContext *js, JSValue self, int argc, JSValue *argv) JSValue js_io_chmod(JSContext *js, JSValue self, int argc, JSValue *argv)
{ {
char *f = js2str(argv[0]); const char *f = js2str(argv[0]);
int mod = js2number(argv[1]); int mod = js2number(argv[1]);
chmod(f, mod); chmod(f, mod);
return JS_UNDEFINED; return JS_UNDEFINED;
@ -2037,7 +2138,7 @@ JSC_CCALL(transform_trs,
transform *t = js2transform(self); transform *t = js2transform(self);
t->pos = JS_IsUndefined(argv[0]) ? v3zero : js2vec3(argv[0]); t->pos = JS_IsUndefined(argv[0]) ? v3zero : js2vec3(argv[0]);
t->rotation = JS_IsUndefined(argv[1]) ? QUAT1 : js2quat(argv[1]); t->rotation = JS_IsUndefined(argv[1]) ? QUAT1 : js2quat(argv[1]);
t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(argv[1]); t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(argv[2]);
) )
static const JSCFunctionListEntry js_transform_funcs[] = { static const JSCFunctionListEntry js_transform_funcs[] = {
@ -2538,8 +2639,7 @@ JSC_GET(texture, width, number)
JSC_GET(texture, height, number) JSC_GET(texture, height, number)
JSC_GET(texture, frames, number) JSC_GET(texture, frames, number)
JSC_GET(texture, delays, ints) JSC_GET(texture, delays, ints)
JSC_GET(texture, size, number) JSC_GET(texture, vram, number)
JSC_GET(texture, gpusize, number)
JSC_SCALL(texture_save, texture_save(js2texture(self), str)); JSC_SCALL(texture_save, texture_save(js2texture(self), str));
@ -2552,16 +2652,18 @@ JSC_CCALL(texture_getid,
return number2js(tex->id.id); return number2js(tex->id.id);
) )
JSC_CCALL(texture_inram, return boolean2js(js2texture(self)->data));
static const JSCFunctionListEntry js_texture_funcs[] = { static const JSCFunctionListEntry js_texture_funcs[] = {
MIST_GET(texture, width), MIST_GET(texture, width),
MIST_GET(texture, height), MIST_GET(texture, height),
MIST_GET(texture, frames), MIST_GET(texture, frames),
MIST_GET(texture, delays), MIST_GET(texture, delays),
MIST_GET(texture, gpusize), MIST_GET(texture, vram),
MIST_GET(texture, size),
MIST_FUNC_DEF(texture, save, 1), MIST_FUNC_DEF(texture, save, 1),
MIST_FUNC_DEF(texture, blit, 5), MIST_FUNC_DEF(texture, blit, 5),
MIST_FUNC_DEF(texture, getid, 0), MIST_FUNC_DEF(texture, getid, 0),
MIST_FUNC_DEF(texture, inram, 0),
}; };
static const JSCFunctionListEntry js_timer_funcs[] = { static const JSCFunctionListEntry js_timer_funcs[] = {
@ -2725,6 +2827,40 @@ JSC_CCALL(os_memstate,
JSJMEMRET(gc_threshold) JSJMEMRET(gc_threshold)
) )
JSC_CCALL(os_mallinfo,
struct mallinfo jsmem = mallinfo();
ret = JS_NewObject(js);
JSJMEMRET(arena);
JSJMEMRET(ordblks);
JSJMEMRET(smblks);
JSJMEMRET(hblks);
JSJMEMRET(hblkhd);
JSJMEMRET(usmblks);
JSJMEMRET(uordblks);
JSJMEMRET(fordblks);
JSJMEMRET(keepcost);
)
JSC_CCALL(os_rusage,
struct rusage jsmem;
getrusage(RUSAGE_SELF, &jsmem);
ret = JS_NewObject(js);
JSJMEMRET(ru_maxrss);
JSJMEMRET(ru_ixrss);
JSJMEMRET(ru_idrss);
JSJMEMRET(ru_isrss);
JSJMEMRET(ru_minflt);
JSJMEMRET(ru_majflt);
JSJMEMRET(ru_nswap);
JSJMEMRET(ru_inblock);
JSJMEMRET(ru_oublock);
JSJMEMRET(ru_msgsnd);
JSJMEMRET(ru_msgrcv);
JSJMEMRET(ru_nsignals);
JSJMEMRET(ru_nvcsw);
JSJMEMRET(ru_nivcsw);
)
JSC_CCALL(os_mem, JSC_CCALL(os_mem,
JSMemoryUsage jsmem; JSMemoryUsage jsmem;
JS_ComputeMemoryUsage(rt, &jsmem); JS_ComputeMemoryUsage(rt, &jsmem);
@ -3221,6 +3357,8 @@ JSC_CCALL(os_skin_calculate,
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, cwd, 0), MIST_FUNC_DEF(os, cwd, 0),
MIST_FUNC_DEF(os, rusage, 0),
MIST_FUNC_DEF(os, mallinfo, 0),
MIST_FUNC_DEF(os, env, 1), MIST_FUNC_DEF(os, env, 1),
MIST_FUNC_DEF(os, sys, 0), MIST_FUNC_DEF(os, sys, 0),
MIST_FUNC_DEF(os, system, 1), MIST_FUNC_DEF(os, system, 1),
@ -3283,11 +3421,11 @@ void ffi_load() {
globalThis = JS_GetGlobalObject(js); globalThis = JS_GetGlobalObject(js);
QJSCLASSPREP(ptr);
QJSCLASSPREP(sg_buffer);
QJSGLOBALCLASS(os); QJSGLOBALCLASS(os);
QJSCLASSPREP_FUNCS(gameobject); QJSCLASSPREP_FUNCS(gameobject);
QJSCLASSPREP_FUNCS(sg_buffer);
QJSCLASSPREP_FUNCS(transform); QJSCLASSPREP_FUNCS(transform);
QJSCLASSPREP_FUNCS(dsp_node); QJSCLASSPREP_FUNCS(dsp_node);
QJSCLASSPREP_FUNCS(warp_gravity); QJSCLASSPREP_FUNCS(warp_gravity);
@ -3311,6 +3449,7 @@ void ffi_load() {
QJSGLOBALCLASS(game); QJSGLOBALCLASS(game);
QJSGLOBALCLASS(gui); QJSGLOBALCLASS(gui);
QJSGLOBALCLASS(render); QJSGLOBALCLASS(render);
// QJSGLOBALCLASS(sgl);
QJSGLOBALCLASS(physics); QJSGLOBALCLASS(physics);
QJSGLOBALCLASS(vector); QJSGLOBALCLASS(vector);
QJSGLOBALCLASS(spline); QJSGLOBALCLASS(spline);

View file

@ -52,6 +52,16 @@ extern JSValue cpShape2js(cpShape *s);
return ret; \ return ret; \
} \ } \
#define JSC_DCALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(); }
#define JSC_1CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0])); }
#define JSC_2CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1])); }
#define JSC_3CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2])); }
#define JSC_4CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3])); }
#define JSC_5CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4])); }
#define JSC_6CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5])); }
#define JSC_7CALL(FN) JSValue js_##FN (JSContext *js, JSValue self, int argc, JSValue *argv) { FN(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5]), js2number(argv[6])); }
#define GETSETPAIR(ID, ENTRY, TYPE, FN) \ #define GETSETPAIR(ID, ENTRY, TYPE, FN) \
JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \ JSValue js_##ID##_set_##ENTRY (JS_SETSIG) { \
js2##ID (self)->ENTRY = js2##TYPE (val); \ js2##ID (self)->ENTRY = js2##TYPE (val); \
@ -95,8 +105,10 @@ JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
#define QJSCLASS(TYPE)\ #define QJSCLASS(TYPE)\
static JSClassID js_##TYPE##_id;\ static JSClassID js_##TYPE##_id;\
static int js_##TYPE##_count = 0; \
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\
js_##TYPE##_count--; \
TYPE##_free(n);}\ TYPE##_free(n);}\
static JSClassDef js_##TYPE##_class = {\ static JSClassDef js_##TYPE##_class = {\
#TYPE,\ #TYPE,\
@ -110,27 +122,28 @@ TYPE *js2##TYPE (JSValue val) { \
JSValue TYPE##2js(TYPE *n) { \ JSValue TYPE##2js(TYPE *n) { \
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
JS_SetOpaque(j,n);\ JS_SetOpaque(j,n);\
js_##TYPE##_count++; \
return j; }\ return j; }\
\ \
static JSValue js_##TYPE##_memid (JSContext *js, JSValue self) { return str2js("%p", js2##TYPE(self)); } \ static JSValue js_##TYPE##_memid (JSContext *js, JSValue self) { return str2js("%p", js2##TYPE(self)); } \
static JSValue js_##TYPE##_memsize (JSContext *js, JSValue self) { return number2js(sizeof(TYPE)); } \ static JSValue js_##TYPE##_memsize (JSContext *js, JSValue self) { return number2js(sizeof(TYPE)); } \
static JSValue js_##TYPE##__count (JSContext *js, JSValue self) { return number2js(js_##TYPE##_count); } \
#define QJSGLOBALCLASS(NAME) \ #define QJSGLOBALCLASS(NAME) \
JSValue NAME = JS_NewObject(js); \ JSValue NAME = JS_NewObject(js); \
JS_SetPropertyFunctionList(js, NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \ JS_SetPropertyFunctionList(js, NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \
JS_SetPropertyStr(js, globalThis, #NAME, NAME); \ JS_SetPropertyStr(js, globalThis, #NAME, NAME); \
#define QJSCLASSPREP(TYPE) \
JS_NewClassID(&js_##TYPE##_id);\
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
/* Defines a class and uses its function list as its prototype */ /* Defines a class and uses its function list as its prototype */
#define QJSCLASSPREP_FUNCS(TYPE) \ #define QJSCLASSPREP_FUNCS(TYPE) \
QJSCLASSPREP(TYPE); \ JS_NewClassID(&js_##TYPE##_id);\
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
JSValue TYPE##_proto = JS_NewObject(js); \ JSValue TYPE##_proto = JS_NewObject(js); \
JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \
JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \ JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \
JS_SetPropertyStr(js, TYPE##_proto, "memsize", JS_NewCFunction(js, &js_##TYPE##_memsize, "memsize", 0)); \ JS_SetPropertyStr(js, TYPE##_proto, "memsize", JS_NewCFunction(js, &js_##TYPE##_memsize, "memsize", 0)); \
JS_SetPropertyStr(js, TYPE##_proto, "_count", JS_NewCFunction(js, &js_##TYPE##__count, "_count", 0)); \
JS_SetPropertyStr(js, globalThis, #TYPE "_proto", JS_DupValue(js,TYPE##_proto)); \
JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
#define countof(x) (sizeof(x)/sizeof((x)[0])) #define countof(x) (sizeof(x)/sizeof((x)[0]))

View file

@ -270,7 +270,7 @@ char *nota_read_text(char **text, char *nota)
return nota; return nota;
} }
char *nota_write_text(char *s, char *nota) char *nota_write_text(const char *s, char *nota)
{ {
nota[0] = NOTA_TEXT; nota[0] = NOTA_TEXT;

View file

@ -33,7 +33,7 @@ char *nota_read_sym(int *sym, char *nota);
void print_nota_hex(char *nota); void print_nota_hex(char *nota);
char *nota_write_blob(unsigned long long n, char *nota); char *nota_write_blob(unsigned long long n, char *nota);
char *nota_write_text(char *s, char *nota); char *nota_write_text(const char *s, char *nota);
char *nota_write_array(unsigned long long n, char *nota); char *nota_write_array(unsigned long long n, char *nota);
char *nota_write_record(unsigned long long n, char *nota); char *nota_write_record(unsigned long long n, char *nota);
char *nota_write_float(double n, char *nota); char *nota_write_float(double n, char *nota);

View file

@ -16,7 +16,7 @@
#include "stb_image_write.h" #include "stb_image_write.h"
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
#include "sokol/util/sokol_gl.h"
#include "gui.h" #include "gui.h"
static HMM_Vec2 lastuse = {0}; static HMM_Vec2 lastuse = {0};
@ -151,6 +151,10 @@ void render_init() {
.buffer_pool_size = 1024, .buffer_pool_size = 1024,
.image_pool_size = 1024, .image_pool_size = 1024,
}); });
// sgl_setup(&(sgl_desc_t){
// .logger.func = sg_logging
// });
std_sampler = sg_make_sampler(&(sg_sampler_desc){}); std_sampler = sg_make_sampler(&(sg_sampler_desc){});
tex_sampler = sg_make_sampler(&(sg_sampler_desc){ tex_sampler = sg_make_sampler(&(sg_sampler_desc){

View file

@ -117,8 +117,7 @@ struct texture *texture_from_file(const char *path) {
return NULL; return NULL;
tex->data = data; tex->data = data;
tex->size = tex->width*tex->height*4; tex->vram = tex->width*tex->height*4;
tex->gpusize = tex->size;
unsigned int nw = next_pow2(tex->width); unsigned int nw = next_pow2(tex->width);
unsigned int nh = next_pow2(tex->height); unsigned int nh = next_pow2(tex->height);
@ -144,7 +143,7 @@ struct texture *texture_from_file(const char *path) {
mipdata[i] = malloc(w * h * 4); mipdata[i] = malloc(w * h * 4);
stbir_resize_uint8_linear(mipdata[i-1], mipw, miph, 0, mipdata[i], w, h, 0, 4); stbir_resize_uint8_linear(mipdata[i-1], mipw, miph, 0, mipdata[i], w, h, 0, 4);
sg_img_data.subimage[0][i] = (sg_range){ .ptr = mipdata[i], .size = w*h*4 }; sg_img_data.subimage[0][i] = (sg_range){ .ptr = mipdata[i], .size = w*h*4 };
tex->gpusize += w*h*4; tex->vram += w*h*4;
mipw = w; mipw = w;
miph = h; miph = h;
@ -161,6 +160,9 @@ struct texture *texture_from_file(const char *path) {
for (int i = 1; i < mips; i++) for (int i = 1; i < mips; i++)
free(mipdata[i]); free(mipdata[i]);
free(tex->data);
tex->data = NULL;
return tex; return tex;
} }
@ -286,6 +288,8 @@ double grad (int hash, double x, double y, double z)
void texture_save(texture *tex, const char *file) void texture_save(texture *tex, const char *file)
{ {
if (!tex->data) return;
char *ext = strrchr(file, '.'); char *ext = strrchr(file, '.');
if (!strcmp(ext, ".png")) if (!strcmp(ext, ".png"))
stbi_write_png(file, tex->width, tex->height, 4, tex->data, 4*tex->width); stbi_write_png(file, tex->width, tex->height, 4, tex->data, 4*tex->width);
@ -339,6 +343,7 @@ void blit_image(uint8_t* src, uint8_t* dest, int src_width, int src_height, int
// Function to draw source image pixels on top of a destination image // Function to draw source image pixels on top of a destination image
// x,y are the pixel coordinates in the destination image, w,h are the amount of pixels to take from the src image. // x,y are the pixel coordinates in the destination image, w,h are the amount of pixels to take from the src image.
void texture_blit(texture *dest, texture *src, int x, int y, int w, int h) { void texture_blit(texture *dest, texture *src, int x, int y, int w, int h) {
if (!dest->data || !src->data) return;
blit_image(src->data, dest->data, src->width, src->height, dest->width, dest->height, x, y, w, h); blit_image(src->data, dest->data, src->width, src->height, dest->width, dest->height, x, y, w, h);
} }

View file

@ -26,10 +26,9 @@ struct texture {
int width; int width;
int height; int height;
unsigned char *data; unsigned char *data;
int size;
int gpusize;
int frames; int frames;
int *delays; int *delays;
int vram;
}; };
typedef struct texture texture; typedef struct texture texture;

View file

@ -18,6 +18,9 @@ void transform_free(transform *t);
#define VEC2_FMT "[%g,%g]" #define VEC2_FMT "[%g,%g]"
#define VEC2_MEMS(s) (s).x, (s).y #define VEC2_MEMS(s) (s).x, (s).y
#define TR_FMT "(pos) " HMMFMT_VEC3 " scale " HMMFMT_VEC3
#define TR_PRINT(tr) HMMPRINT_VEC3(tr->pos), HMMPRINT_VEC3(tr->scale)
void transform_move(transform *t, HMM_Vec3 v); void transform_move(transform *t, HMM_Vec3 v);
HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir); HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir);

View file

@ -66,6 +66,7 @@ void window_setfullscreen(window *w, int f)
void window_seticon(struct window *w, struct texture *tex) void window_seticon(struct window *w, struct texture *tex)
{ {
if (!tex->data) return;
struct isize { struct isize {
int size; int size;
unsigned char *data; unsigned char *data;

View file

@ -215,6 +215,7 @@ static sapp_desc start_desc = {
.height = 1080, .height = 1080,
.high_dpi = 0, .high_dpi = 0,
.sample_count = 1, .sample_count = 1,
.swap_interval = 0,
.fullscreen = 1, .fullscreen = 1,
.window_title = NULL, .window_title = NULL,
.enable_clipboard = false, .enable_clipboard = false,