Compare commits
No commits in common. "04a2f7d3d3030e26bbb14a92313a467a80638d20" and "584418a334d988baacd19218855cae6d04104b29" have entirely different histories.
04a2f7d3d3
...
584418a334
14
README.md
14
README.md
|
|
@ -1,13 +1,3 @@
|
|||
# Majora's Screensaver
|
||||
# screensaver
|
||||
|
||||
Example C program with zig build that can target Windows, Mac and Linux.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. [Download](https://ziglang.org/download/) Zig v0.15.2 (stable)
|
||||
2. Ensure Zig is on your PATH
|
||||
3. Navigate to our project's root directory
|
||||
4. Call `zig build`
|
||||
5. Run `./zig-out/bin/screensaver`
|
||||
|
||||
For Apple users who want a macOS app bundle, call `zig build bundle` instead.
|
||||
Example C program with zig build that can target Windows, Mac and Linux.
|
||||
191
build.zig
191
build.zig
|
|
@ -1,191 +0,0 @@
|
|||
// Majora's Screensaver (expects zig v0.15.x)
|
||||
// @author: Abner Coimbre <abner@terminal.click>
|
||||
// @description: Sample C app for Windows, Mac & Linux. Adapted from floooh's sokol examples.
|
||||
|
||||
// The goal is to demonstrate how to write a cross-platform native app/game in vanilla C, using only Zig to compile.
|
||||
|
||||
// Single-Header Libraries:
|
||||
// - Sokol (https://github.com/floooh/sokol): Windowing, input, and/or graphics
|
||||
// - STB (https://github.com/nothings/stb): Loading images/assets
|
||||
|
||||
// Instructions
|
||||
// ---
|
||||
// 1. Ensure Zig is on your PATH: download from https://ziglang.org/download
|
||||
// 2. Navigate to this project's folder
|
||||
// 3. Run the `zig build` command
|
||||
// 4. For a macOS App Bundle try `zig build bundle` instead
|
||||
// ---
|
||||
// You may now run the executable under zig-out/
|
||||
|
||||
// The command `zig build` executes build() below. Learn more at https://zig.guide/
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Initial exe
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "screensaver",
|
||||
.root_module = b.createModule(.{
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
}),
|
||||
});
|
||||
|
||||
// Compiler flags: update as needed
|
||||
const win_flags = &[_][]const u8{
|
||||
"-DSOKOL_D3D11",
|
||||
"-O0",
|
||||
"-ggdb3",
|
||||
"-std=c99",
|
||||
"-Werror", // Without this we can't emit warnings. This is a Zig bug: https://github.com/ziglang/zig/issues/15912
|
||||
};
|
||||
|
||||
const macos_flags = &[_][]const u8{
|
||||
"-ObjC",
|
||||
"-DSOKOL_METAL",
|
||||
"-O0",
|
||||
"-ggdb3",
|
||||
"-std=c99",
|
||||
"-Werror",
|
||||
};
|
||||
|
||||
const linux_flags = &[_][]const u8{
|
||||
"-DSOKOL_GLCORE33",
|
||||
"-O0",
|
||||
"-ggdb3",
|
||||
"-std=c99",
|
||||
"-Werror",
|
||||
};
|
||||
|
||||
// Add include folder(s)
|
||||
exe.addIncludePath(b.path("inc"));
|
||||
exe.addIncludePath(b.path("data/shaders"));
|
||||
|
||||
// Which OS are we in?
|
||||
const tag = target.result.os.tag;
|
||||
|
||||
// Select appropriate compiler flags
|
||||
const target_flags = switch (tag) {
|
||||
.windows => win_flags,
|
||||
.macos => macos_flags,
|
||||
.linux => linux_flags,
|
||||
else => {
|
||||
std.debug.print("Error: Unsupported OS! Contact abner@terminal.click\n", .{});
|
||||
std.process.exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
// Add our source code
|
||||
exe.addCSourceFile(.{ .file = b.path("main.c"), .flags = target_flags });
|
||||
|
||||
// Link against C's standard library
|
||||
exe.linkLibC();
|
||||
|
||||
// Link against appropriate system libraries
|
||||
switch (tag) {
|
||||
.windows => {
|
||||
exe.linkSystemLibrary("kernel32");
|
||||
exe.linkSystemLibrary("gdi32");
|
||||
exe.linkSystemLibrary("d3d11");
|
||||
},
|
||||
|
||||
.macos => {
|
||||
exe.linkFramework("MetalKit");
|
||||
exe.linkFramework("Metal");
|
||||
exe.linkFramework("Cocoa");
|
||||
exe.linkFramework("QuartzCore");
|
||||
},
|
||||
|
||||
.linux => {
|
||||
exe.linkSystemLibrary("GL");
|
||||
exe.linkSystemLibrary("X11");
|
||||
exe.linkSystemLibrary("Xi");
|
||||
exe.linkSystemLibrary("Xcursor");
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
b.installArtifact(exe);
|
||||
|
||||
//
|
||||
// macOS App Bundle - prepares one if user called `zig build bundle`
|
||||
//
|
||||
// ---
|
||||
if (tag == .macos) {
|
||||
const app_name = "Screensaver";
|
||||
const bundle_path = b.fmt("zig-out/{s}.app/Contents", .{app_name});
|
||||
|
||||
const mkdir = b.addSystemCommand(&.{
|
||||
"mkdir", "-p",
|
||||
b.fmt("{s}/MacOS", .{bundle_path}),
|
||||
});
|
||||
|
||||
const mkdir_res = b.addSystemCommand(&.{
|
||||
"mkdir", "-p",
|
||||
b.fmt("{s}/Resources", .{bundle_path}),
|
||||
});
|
||||
|
||||
const copy_exe = b.addSystemCommand(&.{
|
||||
"cp",
|
||||
b.getInstallPath(.bin, "screensaver"),
|
||||
b.fmt("{s}/MacOS/screensaver", .{bundle_path}),
|
||||
});
|
||||
copy_exe.step.dependOn(&mkdir.step);
|
||||
copy_exe.step.dependOn(b.getInstallStep());
|
||||
|
||||
const plist_content =
|
||||
\\<?xml version="1.0" encoding="UTF-8"?>
|
||||
\\<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
\\<plist version="1.0">
|
||||
\\<dict>
|
||||
\\ <key>CFBundleExecutable</key>
|
||||
\\ <string>screensaver</string>
|
||||
\\ <key>CFBundleIdentifier</key>
|
||||
\\ <string>click.terminal.screensaver</string>
|
||||
\\ <key>CFBundleName</key>
|
||||
\\ <string>Screensaver</string>
|
||||
\\ <key>CFBundlePackageType</key>
|
||||
\\ <string>APPL</string>
|
||||
\\ <key>CFBundleVersion</key>
|
||||
\\ <string>1.0</string>
|
||||
\\</dict>
|
||||
\\</plist>
|
||||
;
|
||||
|
||||
const write_files = b.addWriteFiles();
|
||||
const plist_file = write_files.add("Info.plist", plist_content);
|
||||
const copy_plist = b.addInstallFile(plist_file, b.fmt("{s}.app/Contents/Info.plist", .{app_name}));
|
||||
|
||||
const copy_data = b.addSystemCommand(&.{
|
||||
"cp", "-R",
|
||||
"data",
|
||||
b.fmt("{s}/Resources/", .{bundle_path}),
|
||||
});
|
||||
copy_data.step.dependOn(&mkdir_res.step);
|
||||
|
||||
const bundle_step = b.step("bundle", "Create macOS app bundle");
|
||||
bundle_step.dependOn(©_exe.step);
|
||||
bundle_step.dependOn(©_plist.step);
|
||||
bundle_step.dependOn(&mkdir_res.step);
|
||||
bundle_step.dependOn(©_data.step);
|
||||
bundle_step.dependOn(©_plist.step);
|
||||
}
|
||||
// ---
|
||||
|
||||
//
|
||||
// We're done! Complete Zig's build graph
|
||||
//
|
||||
//---
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
//---
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 960 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 148 KiB |
|
|
@ -1,47 +0,0 @@
|
|||
@module effect
|
||||
@ctype vec2 sgp_vec2
|
||||
@ctype float float
|
||||
|
||||
@vs vs
|
||||
layout(location=0) in vec4 coord;
|
||||
layout(location=1) in vec4 color;
|
||||
layout(location=0) out vec2 texUV;
|
||||
layout(location=1) out vec4 iColor;
|
||||
void main() {
|
||||
gl_Position = vec4(coord.xy, 0.0, 1.0);
|
||||
texUV = coord.zw;
|
||||
iColor = color;
|
||||
}
|
||||
@end
|
||||
|
||||
@fs fs
|
||||
layout(binding=0) uniform texture2D iTexChannel0;
|
||||
layout(binding=1) uniform texture2D iTexChannel1;
|
||||
layout(binding=0) uniform sampler iSmpChannel0;
|
||||
layout(binding=1) uniform sampler iSmpChannel1;
|
||||
layout(binding=1) uniform fs_uniforms {
|
||||
vec2 iVelocity;
|
||||
float iPressure;
|
||||
float iTime;
|
||||
float iWarpiness;
|
||||
float iRatio;
|
||||
float iZoom;
|
||||
float iLevel;
|
||||
};
|
||||
layout(location=0) in vec2 texUV;
|
||||
layout(location=1) in vec4 iColor;
|
||||
layout(location=0) out vec4 fragColor;
|
||||
float noise(vec2 p) {
|
||||
return texture(sampler2D(iTexChannel1, iSmpChannel1), p).r;
|
||||
}
|
||||
void main() {
|
||||
vec3 tex_col = texture(sampler2D(iTexChannel0, iSmpChannel0), texUV).rgb;
|
||||
vec2 fog_uv = (texUV * vec2(iRatio, 1.0)) * iZoom;
|
||||
float f = noise(fog_uv - iVelocity*iTime);
|
||||
f = noise(fog_uv + f*iWarpiness);
|
||||
vec3 col = mix(tex_col, vec3(f) * iColor.rgb, iPressure);
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
||||
@end
|
||||
|
||||
@program program vs fs
|
||||
File diff suppressed because it is too large
Load Diff
12097
inc/sokol/sokol_app.h
12097
inc/sokol/sokol_app.h
File diff suppressed because it is too large
Load Diff
22314
inc/sokol/sokol_gfx.h
22314
inc/sokol/sokol_gfx.h
File diff suppressed because it is too large
Load Diff
|
|
@ -1,162 +0,0 @@
|
|||
#if defined(SOKOL_IMPL) && !defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_INCLUDED
|
||||
/*
|
||||
sokol_glue.h -- glue helper functions for sokol headers
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_GLUE_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
...optionally provide the following macros to override defaults:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_glue.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
sokol_glue.h provides glue helper functions between sokol_gfx.h and sokol_app.h,
|
||||
so that sokol_gfx.h doesn't need to depend on sokol_app.h but can be
|
||||
used with different window system glue libraries.
|
||||
|
||||
PROVIDED FUNCTIONS
|
||||
==================
|
||||
|
||||
sg_environment sglue_environment(void)
|
||||
|
||||
Returns an sg_environment struct initialized by calling sokol_app.h
|
||||
functions. Use this in the sg_setup() call like this:
|
||||
|
||||
sg_setup(&(sg_desc){
|
||||
.environment = sglue_environment(),
|
||||
...
|
||||
});
|
||||
|
||||
sg_swapchain sglue_swapchain(void)
|
||||
|
||||
Returns an sg_swapchain struct initialized by calling sokol_app.h
|
||||
functions. Use this in sg_begin_pass() for a 'swapchain pass' like
|
||||
this:
|
||||
|
||||
sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain(), ... });
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_GLUE_INCLUDED
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_GLUE_API_DECL)
|
||||
#define SOKOL_GLUE_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_GLUE_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GLUE_IMPL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_GLUE_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_GLUE_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_GFX_INCLUDED
|
||||
#error "Please include sokol_gfx.h before sokol_glue.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_GLUE_API_DECL sg_environment sglue_environment(void);
|
||||
SOKOL_GLUE_API_DECL sg_swapchain sglue_swapchain(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* SOKOL_GLUE_INCLUDED */
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_GLUE_IMPL
|
||||
#define SOKOL_GLUE_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_APP_INCLUDED
|
||||
#error "Please include sokol_app.h before the sokol_glue.h implementation"
|
||||
#endif
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
|
||||
|
||||
SOKOL_API_IMPL sg_environment sglue_environment(void) {
|
||||
sg_environment env;
|
||||
memset(&env, 0, sizeof(env));
|
||||
env.defaults.color_format = (sg_pixel_format) sapp_color_format();
|
||||
env.defaults.depth_format = (sg_pixel_format) sapp_depth_format();
|
||||
env.defaults.sample_count = sapp_sample_count();
|
||||
env.metal.device = sapp_metal_get_device();
|
||||
env.d3d11.device = sapp_d3d11_get_device();
|
||||
env.d3d11.device_context = sapp_d3d11_get_device_context();
|
||||
env.wgpu.device = sapp_wgpu_get_device();
|
||||
return env;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL sg_swapchain sglue_swapchain(void) {
|
||||
sg_swapchain swapchain;
|
||||
memset(&swapchain, 0, sizeof(swapchain));
|
||||
swapchain.width = sapp_width();
|
||||
swapchain.height = sapp_height();
|
||||
swapchain.sample_count = sapp_sample_count();
|
||||
swapchain.color_format = (sg_pixel_format)sapp_color_format();
|
||||
swapchain.depth_format = (sg_pixel_format)sapp_depth_format();
|
||||
swapchain.metal.current_drawable = sapp_metal_get_current_drawable();
|
||||
swapchain.metal.depth_stencil_texture = sapp_metal_get_depth_stencil_texture();
|
||||
swapchain.metal.msaa_color_texture = sapp_metal_get_msaa_color_texture();
|
||||
swapchain.d3d11.render_view = sapp_d3d11_get_render_view();
|
||||
swapchain.d3d11.resolve_view = sapp_d3d11_get_resolve_view();
|
||||
swapchain.d3d11.depth_stencil_view = sapp_d3d11_get_depth_stencil_view();
|
||||
swapchain.wgpu.render_view = sapp_wgpu_get_render_view();
|
||||
swapchain.wgpu.resolve_view = sapp_wgpu_get_resolve_view();
|
||||
swapchain.wgpu.depth_stencil_view = sapp_wgpu_get_depth_stencil_view();
|
||||
swapchain.gl.framebuffer = sapp_gl_get_framebuffer();
|
||||
return swapchain;
|
||||
}
|
||||
|
||||
#endif /* SOKOL_GLUE_IMPL */
|
||||
3044
inc/sokol/sokol_gp.h
3044
inc/sokol/sokol_gp.h
File diff suppressed because it is too large
Load Diff
|
|
@ -1,343 +0,0 @@
|
|||
#if defined(SOKOL_IMPL) && !defined(SOKOL_LOG_IMPL)
|
||||
#define SOKOL_LOG_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_LOG_INCLUDED
|
||||
/*
|
||||
sokol_log.h -- common logging callback for sokol headers
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Example code: https://github.com/floooh/sokol-samples
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_LOG_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines when building the implementation:
|
||||
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
|
||||
SOKOL_LOG_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
Optionally define the following for verbose output:
|
||||
|
||||
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
|
||||
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
sokol_log.h provides a default logging callback for other sokol headers.
|
||||
|
||||
To use the default log callback, just include sokol_log.h and provide
|
||||
a function pointer to the 'slog_func' function when setting up the
|
||||
sokol library:
|
||||
|
||||
For instance with sokol_audio.h:
|
||||
|
||||
#include "sokol_log.h"
|
||||
...
|
||||
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
|
||||
|
||||
Logging output goes to stderr and/or a platform specific logging subsystem
|
||||
(which means that in some scenarios you might see logging messages duplicated):
|
||||
|
||||
- Windows: stderr + OutputDebugStringA()
|
||||
- macOS/iOS/Linux: stderr + syslog()
|
||||
- Emscripten: console.info()/warn()/error()
|
||||
- Android: __android_log_write()
|
||||
|
||||
On Windows with sokol_app.h also note the runtime config items to make
|
||||
stdout/stderr output visible on the console for WinMain() applications
|
||||
via sapp_desc.win32_console_attach or sapp_desc.win32_console_create,
|
||||
however when running in a debugger on Windows, the logging output should
|
||||
show up on the debug output UI panel.
|
||||
|
||||
In debug mode, a log message might look like this:
|
||||
|
||||
[sspine][error][id:12] /Users/floh/projects/sokol/util/sokol_spine.h:3472:0:
|
||||
SKELETON_DESC_NO_ATLAS: no atlas object provided in sspine_skeleton_desc.atlas
|
||||
|
||||
The source path and line number is formatted like compiler errors, in some IDEs (like VSCode)
|
||||
such error messages are clickable.
|
||||
|
||||
In release mode, logging is less verbose as to not bloat the executable with string data, but you still get
|
||||
enough information to identify the type and location of an error:
|
||||
|
||||
[sspine][error][id:12][line:3472]
|
||||
|
||||
RULES FOR WRITING YOUR OWN LOGGING FUNCTION
|
||||
===========================================
|
||||
- must be re-entrant because it might be called from different threads
|
||||
- must treat **all** provided string pointers as optional (can be null)
|
||||
- don't store the string pointers, copy the string data instead
|
||||
- must not return for log level panic
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2023 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_LOG_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_LOG_API_DECL)
|
||||
#define SOKOL_LOG_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_LOG_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_LOG_IMPL)
|
||||
#define SOKOL_LOG_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_LOG_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_LOG_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
Plug this function into the 'logger.func' struct item when initializing any of the sokol
|
||||
headers. For instance for sokol_audio.h it would loom like this:
|
||||
|
||||
saudio_setup(&(saudio_desc){
|
||||
.logger = {
|
||||
.func = slog_func
|
||||
}
|
||||
});
|
||||
*/
|
||||
SOKOL_LOG_API_DECL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // SOKOL_LOG_INCLUDED
|
||||
|
||||
// ██ ███ ███ ██████ ██ ███████ ███ ███ ███████ ███ ██ ████████ █████ ████████ ██ ██████ ███ ██
|
||||
// ██ ████ ████ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
|
||||
// ██ ██ ████ ██ ██████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██
|
||||
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
// ██ ██ ██ ██ ███████ ███████ ██ ██ ███████ ██ ████ ██ ██ ██ ██ ██ ██████ ██ ████
|
||||
//
|
||||
// >>implementation
|
||||
#ifdef SOKOL_LOG_IMPL
|
||||
#define SOKOL_LOG_IMPL_INCLUDED (1)
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define SOKOL_DEBUG
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _SOKOL_UNUSED
|
||||
#define _SOKOL_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
// platform detection
|
||||
#if defined(__APPLE__)
|
||||
#define _SLOG_APPLE (1)
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define _SLOG_EMSCRIPTEN (1)
|
||||
#elif defined(_WIN32)
|
||||
#define _SLOG_WINDOWS (1)
|
||||
#elif defined(__ANDROID__)
|
||||
#define _SLOG_ANDROID (1)
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
#define _SLOG_LINUX (1)
|
||||
#else
|
||||
#error "sokol_log.h: unknown platform"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // abort
|
||||
#include <stdio.h> // fputs
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#if defined(_SLOG_EMSCRIPTEN)
|
||||
#include <emscripten/emscripten.h>
|
||||
#elif defined(_SLOG_WINDOWS)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(_SLOG_ANDROID)
|
||||
#include <android/log.h>
|
||||
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
// size of line buffer (on stack!) in bytes including terminating zero
|
||||
#define _SLOG_LINE_LENGTH (512)
|
||||
|
||||
_SOKOL_PRIVATE char* _slog_append(const char* str, char* dst, char* end) {
|
||||
if (str) {
|
||||
char c;
|
||||
while (((c = *str++) != 0) && (dst < (end - 1))) {
|
||||
*dst++ = c;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
return dst;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE char* _slog_itoa(uint32_t x, char* buf, size_t buf_size) {
|
||||
const size_t max_digits_and_null = 11;
|
||||
if (buf_size < max_digits_and_null) {
|
||||
return 0;
|
||||
}
|
||||
char* p = buf + max_digits_and_null;
|
||||
*--p = 0;
|
||||
do {
|
||||
*--p = '0' + (x % 10);
|
||||
x /= 10;
|
||||
} while (x != 0);
|
||||
return p;
|
||||
}
|
||||
|
||||
#if defined(_SLOG_EMSCRIPTEN)
|
||||
EM_JS(void, slog_js_log, (uint32_t level, const char* c_str), {
|
||||
const str = UTF8ToString(c_str);
|
||||
switch (level) {
|
||||
case 0: console.error(str); break;
|
||||
case 1: console.error(str); break;
|
||||
case 2: console.warn(str); break;
|
||||
default: console.info(str); break;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
SOKOL_API_IMPL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data) {
|
||||
_SOKOL_UNUSED(user_data);
|
||||
|
||||
const char* log_level_str;
|
||||
switch (log_level) {
|
||||
case 0: log_level_str = "panic"; break;
|
||||
case 1: log_level_str = "error"; break;
|
||||
case 2: log_level_str = "warning"; break;
|
||||
default: log_level_str = "info"; break;
|
||||
}
|
||||
|
||||
// build log output line
|
||||
char line_buf[_SLOG_LINE_LENGTH];
|
||||
char* str = line_buf;
|
||||
char* end = line_buf + sizeof(line_buf);
|
||||
char num_buf[32];
|
||||
if (tag) {
|
||||
str = _slog_append("[", str, end);
|
||||
str = _slog_append(tag, str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
}
|
||||
str = _slog_append("[", str, end);
|
||||
str = _slog_append(log_level_str, str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
str = _slog_append("[id:", str, end);
|
||||
str = _slog_append(_slog_itoa(log_item, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("]", str, end);
|
||||
// if a filename is provided, build a clickable log message that's compatible with compiler error messages
|
||||
if (filename) {
|
||||
str = _slog_append(" ", str, end);
|
||||
#if defined(_MSC_VER)
|
||||
// MSVC compiler error format
|
||||
str = _slog_append(filename, str, end);
|
||||
str = _slog_append("(", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("): ", str, end);
|
||||
#else
|
||||
// gcc/clang compiler error format
|
||||
str = _slog_append(filename, str, end);
|
||||
str = _slog_append(":", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append(":0: ", str, end);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
str = _slog_append("[line:", str, end);
|
||||
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
|
||||
str = _slog_append("] ", str, end);
|
||||
}
|
||||
if (message) {
|
||||
str = _slog_append("\n\t", str, end);
|
||||
str = _slog_append(message, str, end);
|
||||
}
|
||||
str = _slog_append("\n\n", str, end);
|
||||
if (0 == log_level) {
|
||||
str = _slog_append("ABORTING because of [panic]\n", str, end);
|
||||
(void)str;
|
||||
}
|
||||
|
||||
// print to stderr?
|
||||
#if defined(_SLOG_LINUX) || defined(_SLOG_WINDOWS) || defined(_SLOG_APPLE)
|
||||
fputs(line_buf, stderr);
|
||||
#endif
|
||||
|
||||
// platform specific logging calls
|
||||
#if defined(_SLOG_WINDOWS)
|
||||
OutputDebugStringA(line_buf);
|
||||
#elif defined(_SLOG_ANDROID)
|
||||
int prio;
|
||||
switch (log_level) {
|
||||
case 0: prio = ANDROID_LOG_FATAL; break;
|
||||
case 1: prio = ANDROID_LOG_ERROR; break;
|
||||
case 2: prio = ANDROID_LOG_WARN; break;
|
||||
default: prio = ANDROID_LOG_INFO; break;
|
||||
}
|
||||
__android_log_write(prio, "SOKOL", line_buf);
|
||||
#elif defined(_SLOG_EMSCRIPTEN)
|
||||
slog_js_log(log_level, line_buf);
|
||||
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
|
||||
int prio;
|
||||
switch (log_level) {
|
||||
case 0: prio = LOG_CRIT; break;
|
||||
case 1: prio = LOG_ERR; break;
|
||||
case 2: prio = LOG_WARNING; break;
|
||||
default: prio = LOG_INFO; break;
|
||||
}
|
||||
syslog(prio, "%s", line_buf);
|
||||
#endif
|
||||
if (0 == log_level) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif // SOKOL_LOG_IMPL
|
||||
|
|
@ -1,319 +0,0 @@
|
|||
#if defined(SOKOL_IMPL) && !defined(SOKOL_TIME_IMPL)
|
||||
#define SOKOL_TIME_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_TIME_INCLUDED
|
||||
/*
|
||||
sokol_time.h -- simple cross-platform time measurement
|
||||
|
||||
Project URL: https://github.com/floooh/sokol
|
||||
|
||||
Do this:
|
||||
#define SOKOL_IMPL or
|
||||
#define SOKOL_TIME_IMPL
|
||||
before you include this file in *one* C or C++ file to create the
|
||||
implementation.
|
||||
|
||||
Optionally provide the following defines with your own implementations:
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_TIME_API_DECL - public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_TIME_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
|
||||
If sokol_time.h is compiled as a DLL, define the following before
|
||||
including the declaration or implementation:
|
||||
|
||||
SOKOL_DLL
|
||||
|
||||
On Windows, SOKOL_DLL will define SOKOL_TIME_API_DECL as __declspec(dllexport)
|
||||
or __declspec(dllimport) as needed.
|
||||
|
||||
void stm_setup();
|
||||
Call once before any other functions to initialize sokol_time
|
||||
(this calls for instance QueryPerformanceFrequency on Windows)
|
||||
|
||||
uint64_t stm_now();
|
||||
Get current point in time in unspecified 'ticks'. The value that
|
||||
is returned has no relation to the 'wall-clock' time and is
|
||||
not in a specific time unit, it is only useful to compute
|
||||
time differences.
|
||||
|
||||
uint64_t stm_diff(uint64_t new, uint64_t old);
|
||||
Computes the time difference between new and old. This will always
|
||||
return a positive, non-zero value.
|
||||
|
||||
uint64_t stm_since(uint64_t start);
|
||||
Takes the current time, and returns the elapsed time since start
|
||||
(this is a shortcut for "stm_diff(stm_now(), start)")
|
||||
|
||||
uint64_t stm_laptime(uint64_t* last_time);
|
||||
This is useful for measuring frame time and other recurring
|
||||
events. It takes the current time, returns the time difference
|
||||
to the value in last_time, and stores the current time in
|
||||
last_time for the next call. If the value in last_time is 0,
|
||||
the return value will be zero (this usually happens on the
|
||||
very first call).
|
||||
|
||||
uint64_t stm_round_to_common_refresh_rate(uint64_t duration)
|
||||
This oddly named function takes a measured frame time and
|
||||
returns the closest "nearby" common display refresh rate frame duration
|
||||
in ticks. If the input duration isn't close to any common display
|
||||
refresh rate, the input duration will be returned unchanged as a fallback.
|
||||
The main purpose of this function is to remove jitter/inaccuracies from
|
||||
measured frame times, and instead use the display refresh rate as
|
||||
frame duration.
|
||||
NOTE: for more robust frame timing, consider using the
|
||||
sokol_app.h function sapp_frame_duration()
|
||||
|
||||
Use the following functions to convert a duration in ticks into
|
||||
useful time units:
|
||||
|
||||
double stm_sec(uint64_t ticks);
|
||||
double stm_ms(uint64_t ticks);
|
||||
double stm_us(uint64_t ticks);
|
||||
double stm_ns(uint64_t ticks);
|
||||
Converts a tick value into seconds, milliseconds, microseconds
|
||||
or nanoseconds. Note that not all platforms will have nanosecond
|
||||
or even microsecond precision.
|
||||
|
||||
Uses the following time measurement functions under the hood:
|
||||
|
||||
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
|
||||
MacOS/iOS: mach_absolute_time()
|
||||
emscripten: emscripten_get_now()
|
||||
Linux+others: clock_gettime(CLOCK_MONOTONIC)
|
||||
|
||||
zlib/libpng license
|
||||
|
||||
Copyright (c) 2018 Andre Weissflog
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the
|
||||
use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_TIME_INCLUDED (1)
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(SOKOL_API_DECL) && !defined(SOKOL_TIME_API_DECL)
|
||||
#define SOKOL_TIME_API_DECL SOKOL_API_DECL
|
||||
#endif
|
||||
#ifndef SOKOL_TIME_API_DECL
|
||||
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_TIME_IMPL)
|
||||
#define SOKOL_TIME_API_DECL __declspec(dllexport)
|
||||
#elif defined(_WIN32) && defined(SOKOL_DLL)
|
||||
#define SOKOL_TIME_API_DECL __declspec(dllimport)
|
||||
#else
|
||||
#define SOKOL_TIME_API_DECL extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
SOKOL_TIME_API_DECL void stm_setup(void);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_now(void);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_since(uint64_t start_ticks);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_laptime(uint64_t* last_time);
|
||||
SOKOL_TIME_API_DECL uint64_t stm_round_to_common_refresh_rate(uint64_t frame_ticks);
|
||||
SOKOL_TIME_API_DECL double stm_sec(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_ms(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_us(uint64_t ticks);
|
||||
SOKOL_TIME_API_DECL double stm_ns(uint64_t ticks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif // SOKOL_TIME_INCLUDED
|
||||
|
||||
/*-- IMPLEMENTATION ----------------------------------------------------------*/
|
||||
#ifdef SOKOL_TIME_IMPL
|
||||
#define SOKOL_TIME_IMPL_INCLUDED (1)
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifndef SOKOL_API_IMPL
|
||||
#define SOKOL_API_IMPL
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#ifndef _SOKOL_PRIVATE
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define _SOKOL_PRIVATE __attribute__((unused)) static
|
||||
#else
|
||||
#define _SOKOL_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
LARGE_INTEGER freq;
|
||||
LARGE_INTEGER start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
#include <mach/mach_time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
mach_timebase_info_data_t timebase;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include <emscripten/emscripten.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
double start;
|
||||
} _stm_state_t;
|
||||
#else /* anything else, this will need more care for non-Linux platforms */
|
||||
#ifdef ESP8266
|
||||
// On the ESP8266, clock_gettime ignores the first argument and CLOCK_MONOTONIC isn't defined
|
||||
#define CLOCK_MONOTONIC 0
|
||||
#endif
|
||||
#include <time.h>
|
||||
typedef struct {
|
||||
uint32_t initialized;
|
||||
uint64_t start;
|
||||
} _stm_state_t;
|
||||
#endif
|
||||
static _stm_state_t _stm;
|
||||
|
||||
/* prevent 64-bit overflow when computing relative timestamp
|
||||
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
|
||||
*/
|
||||
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
|
||||
_SOKOL_PRIVATE int64_t _stm_int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
|
||||
int64_t q = value / denom;
|
||||
int64_t r = value % denom;
|
||||
return q * numer + r * numer / denom;
|
||||
}
|
||||
#endif
|
||||
|
||||
SOKOL_API_IMPL void stm_setup(void) {
|
||||
memset(&_stm, 0, sizeof(_stm));
|
||||
_stm.initialized = 0xABCDABCD;
|
||||
#if defined(_WIN32)
|
||||
QueryPerformanceFrequency(&_stm.freq);
|
||||
QueryPerformanceCounter(&_stm.start);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
mach_timebase_info(&_stm.timebase);
|
||||
_stm.start = mach_absolute_time();
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
_stm.start = emscripten_get_now();
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
_stm.start = (uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_now(void) {
|
||||
SOKOL_ASSERT(_stm.initialized == 0xABCDABCD);
|
||||
uint64_t now;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER qpc_t;
|
||||
QueryPerformanceCounter(&qpc_t);
|
||||
now = (uint64_t) _stm_int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
const uint64_t mach_now = mach_absolute_time() - _stm.start;
|
||||
now = (uint64_t) _stm_int64_muldiv((int64_t)mach_now, (int64_t)_stm.timebase.numer, (int64_t)_stm.timebase.denom);
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
double js_now = emscripten_get_now() - _stm.start;
|
||||
now = (uint64_t) (js_now * 1000000.0);
|
||||
#else
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ((uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec) - _stm.start;
|
||||
#endif
|
||||
return now;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks) {
|
||||
if (new_ticks > old_ticks) {
|
||||
return new_ticks - old_ticks;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks) {
|
||||
return stm_diff(stm_now(), start_ticks);
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
|
||||
SOKOL_ASSERT(last_time);
|
||||
uint64_t dt = 0;
|
||||
uint64_t now = stm_now();
|
||||
if (0 != *last_time) {
|
||||
dt = stm_diff(now, *last_time);
|
||||
}
|
||||
*last_time = now;
|
||||
return dt;
|
||||
}
|
||||
|
||||
// first number is frame duration in ns, second number is tolerance in ns,
|
||||
// the resulting min/max values must not overlap!
|
||||
static const uint64_t _stm_refresh_rates[][2] = {
|
||||
{ 16666667, 1000000 }, // 60 Hz: 16.6667 +- 1ms
|
||||
{ 13888889, 250000 }, // 72 Hz: 13.8889 +- 0.25ms
|
||||
{ 13333333, 250000 }, // 75 Hz: 13.3333 +- 0.25ms
|
||||
{ 11764706, 250000 }, // 85 Hz: 11.7647 +- 0.25
|
||||
{ 11111111, 250000 }, // 90 Hz: 11.1111 +- 0.25ms
|
||||
{ 10000000, 500000 }, // 100 Hz: 10.0000 +- 0.5ms
|
||||
{ 8333333, 500000 }, // 120 Hz: 8.3333 +- 0.5ms
|
||||
{ 6944445, 500000 }, // 144 Hz: 6.9445 +- 0.5ms
|
||||
{ 4166667, 1000000 }, // 240 Hz: 4.1666 +- 1ms
|
||||
{ 0, 0 }, // keep the last element always at zero
|
||||
};
|
||||
|
||||
SOKOL_API_IMPL uint64_t stm_round_to_common_refresh_rate(uint64_t ticks) {
|
||||
uint64_t ns;
|
||||
int i = 0;
|
||||
while (0 != (ns = _stm_refresh_rates[i][0])) {
|
||||
uint64_t tol = _stm_refresh_rates[i][1];
|
||||
if ((ticks > (ns - tol)) && (ticks < (ns + tol))) {
|
||||
return ns;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// fallthrough: didn't fit into any buckets
|
||||
return ticks;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_sec(uint64_t ticks) {
|
||||
return (double)ticks / 1000000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ms(uint64_t ticks) {
|
||||
return (double)ticks / 1000000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_us(uint64_t ticks) {
|
||||
return (double)ticks / 1000.0;
|
||||
}
|
||||
|
||||
SOKOL_API_IMPL double stm_ns(uint64_t ticks) {
|
||||
return (double)ticks;
|
||||
}
|
||||
#endif /* SOKOL_TIME_IMPL */
|
||||
|
||||
6755
inc/stb/stb_image.h
6755
inc/stb/stb_image.h
File diff suppressed because it is too large
Load Diff
206
main.c
206
main.c
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
* This screensaver demonstrates 2D shader effects through multiple textures.
|
||||
*/
|
||||
|
||||
#define SGP_UNIFORM_CONTENT_SLOTS 16
|
||||
#define SOKOL_IMPL
|
||||
#include "sokol/sokol_gfx.h"
|
||||
#include "sokol/sokol_gp.h"
|
||||
#include "sokol/sokol_app.h"
|
||||
#include "sokol/sokol_glue.h"
|
||||
#include "sokol/sokol_log.h"
|
||||
#include "sokol/sokol_time.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_STATIC
|
||||
#define STBI_NO_SIMD
|
||||
#define STBI_ONLY_PNG
|
||||
#include "stb/stb_image.h"
|
||||
|
||||
#define SOKOL_SHDC_IMPL
|
||||
#include "sample-effect.glsl.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void set_macos_working_directory(void) {
|
||||
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||
if (bundle) {
|
||||
CFStringRef id = CFBundleGetIdentifier(bundle);
|
||||
if (id) {
|
||||
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
|
||||
if (resourcesURL) {
|
||||
char path[PATH_MAX];
|
||||
if (CFURLGetFileSystemRepresentation(resourcesURL, true, (UInt8*)path, PATH_MAX)) {
|
||||
chdir(path);
|
||||
}
|
||||
CFRelease(resourcesURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static sg_pipeline pip;
|
||||
static sg_shader shd;
|
||||
static sg_image image;
|
||||
static sg_sampler linear_sampler;
|
||||
static sg_image perlin_image;
|
||||
|
||||
static void event(const sapp_event* ev) {
|
||||
switch (ev->type) {
|
||||
case SAPP_EVENTTYPE_KEY_DOWN:
|
||||
if (ev->key_code == SAPP_KEYCODE_ESCAPE)
|
||||
sapp_request_quit();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void frame(void) {
|
||||
// begin draw commands queue
|
||||
int window_width = sapp_width(), window_height = sapp_height();
|
||||
sgp_begin(window_width, window_height);
|
||||
|
||||
float secs = sapp_frame_count() * sapp_frame_duration();
|
||||
sg_image_desc image_desc = sg_query_image_desc(image);
|
||||
float window_ratio = window_width / (float)window_height;
|
||||
float image_ratio = image_desc.width / (float)image_desc.height;
|
||||
effect_fs_uniforms_t uniforms = {0};
|
||||
uniforms.iVelocity.x = 0.02f;
|
||||
uniforms.iVelocity.y = 0.01f;
|
||||
uniforms.iPressure = 0.3f;
|
||||
uniforms.iTime = secs;
|
||||
uniforms.iWarpiness = 0.2f;
|
||||
uniforms.iRatio = image_ratio;
|
||||
uniforms.iZoom = 0.4f;
|
||||
uniforms.iLevel = 1.0f;
|
||||
sgp_set_pipeline(pip);
|
||||
sgp_set_pipeline(pip);
|
||||
sgp_set_uniform(NULL, 0, &uniforms, sizeof(effect_fs_uniforms_t));
|
||||
sgp_set_image(IMG_iTexChannel0, image);
|
||||
sgp_set_image(IMG_iTexChannel1, perlin_image);
|
||||
sgp_set_sampler(SMP_iSmpChannel0, linear_sampler);
|
||||
sgp_set_sampler(SMP_iSmpChannel1, linear_sampler);
|
||||
float width = (window_ratio >= image_ratio) ? window_width : image_ratio*window_height;
|
||||
float height = (window_ratio >= image_ratio) ? window_width/image_ratio : window_height;
|
||||
sgp_draw_filled_rect(0, 0, width, height);
|
||||
sgp_reset_image(IMG_iTexChannel0);
|
||||
sgp_reset_image(IMG_iTexChannel1);
|
||||
sgp_reset_sampler(SMP_iSmpChannel0);
|
||||
sgp_reset_sampler(SMP_iSmpChannel1);
|
||||
sgp_reset_pipeline();
|
||||
|
||||
// dispatch draw commands
|
||||
sg_pass pass = {.swapchain = sglue_swapchain()};
|
||||
sg_begin_pass(&pass);
|
||||
sgp_flush();
|
||||
sgp_end();
|
||||
sg_end_pass();
|
||||
sg_commit();
|
||||
}
|
||||
|
||||
|
||||
static sg_image load_image(const char *filename) {
|
||||
int width, height, channels;
|
||||
uint8_t* data = stbi_load(filename, &width, &height, &channels, 4);
|
||||
sg_image img = {SG_INVALID_ID};
|
||||
if(!data)
|
||||
return img;
|
||||
sg_image_desc image_desc = {0};
|
||||
image_desc.width = width;
|
||||
image_desc.height = height;
|
||||
image_desc.data.subimage[0][0].ptr = data;
|
||||
image_desc.data.subimage[0][0].size = (size_t)(width * height * 4);
|
||||
img = sg_make_image(&image_desc);
|
||||
stbi_image_free(data);
|
||||
return img;
|
||||
}
|
||||
|
||||
static void init(void) {
|
||||
#ifdef __APPLE__
|
||||
set_macos_working_directory();
|
||||
#endif
|
||||
|
||||
// Initialize Sokol GFX
|
||||
sg_desc sgdesc = {
|
||||
.environment = sglue_environment(),
|
||||
.logger.func = slog_func
|
||||
};
|
||||
sg_setup(&sgdesc);
|
||||
if (!sg_isvalid()) {
|
||||
fprintf(stderr, "Failed to create Sokol GFX context!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Initialize Sokol GP
|
||||
sgp_desc sgpdesc = {0};
|
||||
sgp_setup(&sgpdesc);
|
||||
if (!sgp_is_valid()) {
|
||||
fprintf(stderr, "Failed to create Sokol GP context: %s\n", sgp_get_error_message(sgp_get_last_error()));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Load image
|
||||
image = load_image("data/images/majora.png");
|
||||
perlin_image = load_image("data/images/perlin.png");
|
||||
if (sg_query_image_state(image) != SG_RESOURCESTATE_VALID || sg_query_image_state(perlin_image) != SG_RESOURCESTATE_VALID) {
|
||||
fprintf(stderr, "failed to load images");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Create linear sampler
|
||||
sg_sampler_desc linear_sampler_desc = {
|
||||
.min_filter = SG_FILTER_LINEAR,
|
||||
.mag_filter = SG_FILTER_LINEAR,
|
||||
.wrap_u = SG_WRAP_REPEAT,
|
||||
.wrap_v = SG_WRAP_REPEAT,
|
||||
};
|
||||
linear_sampler = sg_make_sampler(&linear_sampler_desc);
|
||||
if (sg_query_sampler_state(linear_sampler) != SG_RESOURCESTATE_VALID) {
|
||||
fprintf(stderr, "failed to create linear sampler");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Initialize shader
|
||||
shd = sg_make_shader(effect_program_shader_desc(sg_query_backend()));
|
||||
if (sg_query_shader_state(shd) != SG_RESOURCESTATE_VALID) {
|
||||
fprintf(stderr, "failed to make custom pipeline shader\n");
|
||||
exit(-1);
|
||||
}
|
||||
sgp_pipeline_desc pip_desc = {0};
|
||||
pip_desc.shader = shd;
|
||||
pip_desc.has_vs_color = true;
|
||||
pip = sgp_make_pipeline(&pip_desc);
|
||||
if (sg_query_pipeline_state(pip) != SG_RESOURCESTATE_VALID) {
|
||||
fprintf(stderr, "failed to make custom pipeline\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
sg_destroy_image(image);
|
||||
sg_destroy_image(perlin_image);
|
||||
sg_destroy_pipeline(pip);
|
||||
sgp_shutdown();
|
||||
sg_shutdown();
|
||||
}
|
||||
|
||||
sapp_desc sokol_main(int argc, char* argv[]) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return (sapp_desc){
|
||||
.window_title = "Majora's Screensaver",
|
||||
.width = 700,
|
||||
.height = 720,
|
||||
.high_dpi = true,
|
||||
.init_cb = init,
|
||||
.event_cb = event,
|
||||
.frame_cb = frame,
|
||||
.cleanup_cb = cleanup,
|
||||
.logger.func = slog_func,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue