first commit
BIN
assets/models/cube.m3d
Normal file
BIN
assets/models/test_char.m3d
Normal file
BIN
assets/models/yoda.m3d
Normal file
BIN
assets/shaders/pbr.frag.spv
Normal file
BIN
assets/shaders/pbr.vert.spv
Normal file
BIN
assets/textures/cheesoid.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
assets/textures/ham_smoke.png
Normal file
|
After Width: | Height: | Size: 728 KiB |
BIN
assets/textures/hamster.png
Normal file
|
After Width: | Height: | Size: 961 KiB |
BIN
assets/textures/hog.jpg
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
assets/textures/patamon.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
assets/textures/pattermon.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
assets/textures/purplemon.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
32
build-shaders.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# glslc
|
||||||
|
glsl_compile="glslc"
|
||||||
|
glsl_flags="--target-spv=spv1.6 -std=460"
|
||||||
|
glsl_stage_vert="-fshader-stage=vert"
|
||||||
|
glsl_stage_frag="-fshader-stage=frag"
|
||||||
|
glsl_stage_tesc="-fshader-stage=tesc"
|
||||||
|
glsl_stage_tese="-fshader-stage=tese"
|
||||||
|
glsl_stage_geom="-fshader-stage=geom"
|
||||||
|
glsl_stage_comp="-fshader-stage=comp"
|
||||||
|
glsl_out="-o./assets/shaders/"
|
||||||
|
|
||||||
|
# SPIR-V
|
||||||
|
mkdir -p ./assets/shaders
|
||||||
|
|
||||||
|
for file in ./src/shaders/*.glsl; do
|
||||||
|
base_name=$(basename -- "$file" .glsl)
|
||||||
|
|
||||||
|
case "$base_name" in
|
||||||
|
*.vert) glsl_stage="${glsl_stage_vert}" ;;
|
||||||
|
*.frag) glsl_stage="${glsl_stage_frag}" ;;
|
||||||
|
*.tesc) glsl_stage="${glsl_stage_tesc}" ;;
|
||||||
|
*.tese) glsl_stage="${glsl_stage_tese}" ;;
|
||||||
|
*.geom) glsl_stage="${glsl_stage_geom}" ;;
|
||||||
|
*.comp) glsl_stage="${glsl_stage_comp}" ;;
|
||||||
|
*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$glsl_compile $glsl_flags $glsl_stage $file "${glsl_out}${base_name}.spv"
|
||||||
|
done
|
||||||
87
build.sh
Executable file
@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
|
||||||
|
for arg in "$@"; do declare $arg="1"; done
|
||||||
|
if [ ! -v clang ]; then gcc=1; fi
|
||||||
|
if [ ! -v release ]; then debug=1; fi
|
||||||
|
if [ -v debug ]; then echo "[debug mode]"; fi
|
||||||
|
if [ -v release ]; then echo "[release mode]"; fi
|
||||||
|
if [ -v gcc ]; then compiler="g++"; echo "[gcc compiler]"; fi
|
||||||
|
if [ -v clang ]; then compiler="clang++"; echo "[clang compiler]"; fi
|
||||||
|
|
||||||
|
if [ -v shaders ]; then
|
||||||
|
echo "Bulding shaders..."
|
||||||
|
/bin/bash ./build-shaders.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Axle
|
||||||
|
src="../src/entry_linux.cpp"
|
||||||
|
includes="-I../src/ -I../external/ -I../external/glad/include"
|
||||||
|
out="-o"
|
||||||
|
name="Axle"
|
||||||
|
linker_cmd=" "
|
||||||
|
link="-lpthread -lm -lrt -ldl -lxcb -lX11 -lGL -lXrandr"
|
||||||
|
|
||||||
|
# Codegen
|
||||||
|
codegen_src="../src/codegen.cpp"
|
||||||
|
codegen_name="Codegen"
|
||||||
|
codegen_flag="-DBUILD_CODEGEN"
|
||||||
|
|
||||||
|
# Packer
|
||||||
|
packer_src="../src/packer.cpp"
|
||||||
|
packer_name="Packer"
|
||||||
|
packer_flag="-DBUILD_PACKER"
|
||||||
|
|
||||||
|
if [ -x "$(command -v mold)" ]; then
|
||||||
|
linker_cmd="-fuse-ld=mold"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# clang
|
||||||
|
clang_common="${includes} ${linker_cmd} -DCOMPILER_CLANG -std=c++11 -Xclang -flto-visibility-public-std -Wno-write-strings -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-initializer-overrides -Wno-for-loop-analysis -ferror-limit=60"
|
||||||
|
clang_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${clang_common}"
|
||||||
|
clang_release="$compiler -O2 ${clang_common}"
|
||||||
|
clang_test="$compiler -O2 -DBUILD_TEST=1 ${clang_common}"
|
||||||
|
|
||||||
|
# gcc
|
||||||
|
gcc_common="${includes} ${linker_cmd} -DCOMPILER_GCC -std=c++11 -fmax-errors=5 -Wall -Wno-write-strings -Wno-missing-braces -Wno-unused-function -Wno-attributes -Wno-unused-value -Wno-unused-variable -Wno-deprecated-declarations -Wno-unused-but-set-variable -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -fzero-init-padding-bits=unions"
|
||||||
|
gcc_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${gcc_common}"
|
||||||
|
gcc_release="$compiler -O2 ${gcc_common}"
|
||||||
|
gcc_test="$compiler -O0 -DBUILD_TEST=1 ${gcc_common}"
|
||||||
|
|
||||||
|
if [ -v gcc ]; then compile_debug="$gcc_debug"; fi
|
||||||
|
if [ -v gcc ]; then compile_release="$gcc_release"; fi
|
||||||
|
|
||||||
|
if [ -v clang ]; then compile_debug="$clang_debug"; fi
|
||||||
|
if [ -v clang ]; then compile_release="$clang_release"; fi
|
||||||
|
|
||||||
|
if [ -v debug ]; then compile="$compile_debug"; fi
|
||||||
|
if [ -v release ]; then compile="$compile_release"; fi
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
|
||||||
|
cd assets
|
||||||
|
|
||||||
|
mkdir -p shaders
|
||||||
|
|
||||||
|
cd ../build
|
||||||
|
|
||||||
|
if [ -v codegen ]; then
|
||||||
|
echo "Building codegen..."
|
||||||
|
$compile $codegen_src $codegen_flag $link $out $codegen_name
|
||||||
|
./$codegen_name
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -v packer ]; then
|
||||||
|
echo "Building packer..."
|
||||||
|
$compile $packer_src $packer_flag $link $out $packer_name
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -v pack ]; then
|
||||||
|
echo "Packing assets..."
|
||||||
|
./$packer_name
|
||||||
|
./$codegen_name
|
||||||
|
fi
|
||||||
|
|
||||||
|
$compile $src $link $out $name
|
||||||
|
|
||||||
175
external/glad/include/EGL/eglplatform.h
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#ifndef __eglplatform_h_
|
||||||
|
#define __eglplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright 2007-2020 The Khronos Group Inc.
|
||||||
|
** SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Platform-specific types and definitions for egl.h
|
||||||
|
*
|
||||||
|
* Adopters may modify khrplatform.h and this file to suit their platform.
|
||||||
|
* You are encouraged to submit all modifications to the Khronos group so that
|
||||||
|
* they can be included in future versions of this file. Please submit changes
|
||||||
|
* by filing an issue or pull request on the public Khronos EGL Registry, at
|
||||||
|
* https://www.github.com/KhronosGroup/EGL-Registry/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <KHR/khrplatform.h>
|
||||||
|
|
||||||
|
/* Macros used in EGL function prototype declarations.
|
||||||
|
*
|
||||||
|
* EGL functions should be prototyped as:
|
||||||
|
*
|
||||||
|
* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
|
||||||
|
* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EGLAPI
|
||||||
|
#define EGLAPI KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EGLAPIENTRY
|
||||||
|
#define EGLAPIENTRY KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
#define EGLAPIENTRYP EGLAPIENTRY*
|
||||||
|
|
||||||
|
/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
|
||||||
|
* are aliases of window-system-dependent types, such as X Display * or
|
||||||
|
* Windows Device Context. They must be defined in platform-specific
|
||||||
|
* code below. The EGL-prefixed versions of Native*Type are the same
|
||||||
|
* types, renamed in EGL 1.3 so all types in the API start with "EGL".
|
||||||
|
*
|
||||||
|
* Khronos STRONGLY RECOMMENDS that you use the default definitions
|
||||||
|
* provided below, since these changes affect both binary and source
|
||||||
|
* portability of applications using EGL running on different EGL
|
||||||
|
* implementations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(EGL_NO_PLATFORM_SPECIFIC_TYPES)
|
||||||
|
|
||||||
|
typedef void *EGLNativeDisplayType;
|
||||||
|
typedef void *EGLNativePixmapType;
|
||||||
|
typedef void *EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
typedef HDC EGLNativeDisplayType;
|
||||||
|
typedef HBITMAP EGLNativePixmapType;
|
||||||
|
typedef HWND EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__QNX__)
|
||||||
|
|
||||||
|
typedef khronos_uintptr_t EGLNativeDisplayType;
|
||||||
|
typedef struct _screen_pixmap* EGLNativePixmapType; /* screen_pixmap_t */
|
||||||
|
typedef struct _screen_window* EGLNativeWindowType; /* screen_window_t */
|
||||||
|
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
|
||||||
|
typedef int EGLNativeDisplayType;
|
||||||
|
typedef int EGLNativePixmapType;
|
||||||
|
typedef int EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
|
||||||
|
|
||||||
|
typedef int EGLNativeDisplayType;
|
||||||
|
typedef void *EGLNativePixmapType;
|
||||||
|
typedef void *EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(WL_EGL_PLATFORM)
|
||||||
|
|
||||||
|
typedef struct wl_display *EGLNativeDisplayType;
|
||||||
|
typedef struct wl_egl_pixmap *EGLNativePixmapType;
|
||||||
|
typedef struct wl_egl_window *EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__GBM__)
|
||||||
|
|
||||||
|
typedef struct gbm_device *EGLNativeDisplayType;
|
||||||
|
typedef struct gbm_bo *EGLNativePixmapType;
|
||||||
|
typedef void *EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__ANDROID__) || defined(ANDROID)
|
||||||
|
|
||||||
|
struct ANativeWindow;
|
||||||
|
struct egl_native_pixmap_t;
|
||||||
|
|
||||||
|
typedef void* EGLNativeDisplayType;
|
||||||
|
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
|
||||||
|
typedef struct ANativeWindow* EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(USE_OZONE)
|
||||||
|
|
||||||
|
typedef intptr_t EGLNativeDisplayType;
|
||||||
|
typedef intptr_t EGLNativePixmapType;
|
||||||
|
typedef intptr_t EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(USE_X11)
|
||||||
|
|
||||||
|
/* X11 (tentative) */
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
|
typedef Display *EGLNativeDisplayType;
|
||||||
|
typedef Pixmap EGLNativePixmapType;
|
||||||
|
typedef Window EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__unix__)
|
||||||
|
|
||||||
|
typedef void *EGLNativeDisplayType;
|
||||||
|
typedef khronos_uintptr_t EGLNativePixmapType;
|
||||||
|
typedef khronos_uintptr_t EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
typedef int EGLNativeDisplayType;
|
||||||
|
typedef void *EGLNativePixmapType;
|
||||||
|
typedef void *EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
|
||||||
|
#include <kernel/image.h>
|
||||||
|
|
||||||
|
typedef void *EGLNativeDisplayType;
|
||||||
|
typedef khronos_uintptr_t EGLNativePixmapType;
|
||||||
|
typedef khronos_uintptr_t EGLNativeWindowType;
|
||||||
|
|
||||||
|
#elif defined(__Fuchsia__)
|
||||||
|
|
||||||
|
typedef void *EGLNativeDisplayType;
|
||||||
|
typedef khronos_uintptr_t EGLNativePixmapType;
|
||||||
|
typedef khronos_uintptr_t EGLNativeWindowType;
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Platform not recognized"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
|
||||||
|
typedef EGLNativeDisplayType NativeDisplayType;
|
||||||
|
typedef EGLNativePixmapType NativePixmapType;
|
||||||
|
typedef EGLNativeWindowType NativeWindowType;
|
||||||
|
|
||||||
|
|
||||||
|
/* Define EGLint. This must be a signed integral type large enough to contain
|
||||||
|
* all legal attribute names and values passed into and out of EGL, whether
|
||||||
|
* their type is boolean, bitmask, enumerant (symbolic constant), integer,
|
||||||
|
* handle, or other. While in general a 32-bit integer will suffice, if
|
||||||
|
* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
|
||||||
|
* integer type.
|
||||||
|
*/
|
||||||
|
typedef khronos_int32_t EGLint;
|
||||||
|
|
||||||
|
|
||||||
|
/* C++ / C typecast macros for special EGL handle values */
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#define EGL_CAST(type, value) (static_cast<type>(value))
|
||||||
|
#else
|
||||||
|
#define EGL_CAST(type, value) ((type) (value))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __eglplatform_h */
|
||||||
311
external/glad/include/KHR/khrplatform.h
vendored
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||||
|
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||||
|
* The last semantic modification to khrplatform.h was at commit ID:
|
||||||
|
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by filing pull requests or issues on
|
||||||
|
* the EGL Registry repository linked above.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||||
|
# define KHRONOS_STATIC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(KHRONOS_STATIC)
|
||||||
|
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||||
|
* header compatible with static linking. */
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
/*
|
||||||
|
* To support platform where unsigned long cannot be used interchangeably with
|
||||||
|
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||||
|
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||||
|
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||||
|
* unsigned long long or similar (this results in different C++ name mangling).
|
||||||
|
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||||
|
* platforms where the size of a pointer is larger than the size of long.
|
||||||
|
*/
|
||||||
|
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||||
|
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||||
|
#define KHRONOS_USE_INTPTR_T
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef KHRONOS_USE_INTPTR_T
|
||||||
|
typedef intptr_t khronos_intptr_t;
|
||||||
|
typedef uintptr_t khronos_uintptr_t;
|
||||||
|
#elif defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
||||||
550
external/glad/include/glad/egl.h
vendored
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
/**
|
||||||
|
* Loader generated by glad 2.0.8 on Sat Jun 7 19:05:25 2025
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||||
|
*
|
||||||
|
* Generator: C/C++
|
||||||
|
* Specification: egl
|
||||||
|
* Extensions: 0
|
||||||
|
*
|
||||||
|
* APIs:
|
||||||
|
* - egl=1.5
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* - ALIAS = False
|
||||||
|
* - DEBUG = False
|
||||||
|
* - HEADER_ONLY = False
|
||||||
|
* - LOADER = True
|
||||||
|
* - MX = False
|
||||||
|
* - ON_DEMAND = False
|
||||||
|
*
|
||||||
|
* Commandline:
|
||||||
|
* --api='egl=1.5' --extensions='' c --loader
|
||||||
|
*
|
||||||
|
* Online:
|
||||||
|
* http://glad.sh/#api=egl%3D1.5&extensions=&generator=c&options=LOADER
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLAD_EGL_H_
|
||||||
|
#define GLAD_EGL_H_
|
||||||
|
|
||||||
|
|
||||||
|
#define GLAD_EGL
|
||||||
|
#define GLAD_OPTION_EGL_LOADER
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_H_
|
||||||
|
#define GLAD_PLATFORM_H_
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_WIN32
|
||||||
|
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
|
||||||
|
#define GLAD_PLATFORM_WIN32 1
|
||||||
|
#else
|
||||||
|
#define GLAD_PLATFORM_WIN32 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_APPLE
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define GLAD_PLATFORM_APPLE 1
|
||||||
|
#else
|
||||||
|
#define GLAD_PLATFORM_APPLE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_EMSCRIPTEN
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#define GLAD_PLATFORM_EMSCRIPTEN 1
|
||||||
|
#else
|
||||||
|
#define GLAD_PLATFORM_EMSCRIPTEN 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_UWP
|
||||||
|
#if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<winapifamily.h>)
|
||||||
|
#define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
|
||||||
|
#endif
|
||||||
|
#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
|
||||||
|
#define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
|
||||||
|
#include <winapifamily.h>
|
||||||
|
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||||
|
#define GLAD_PLATFORM_UWP 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAD_PLATFORM_UWP
|
||||||
|
#define GLAD_PLATFORM_UWP 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define GLAD_GNUC_EXTENSION __extension__
|
||||||
|
#else
|
||||||
|
#define GLAD_GNUC_EXTENSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GLAD_UNUSED(x) (void)(x)
|
||||||
|
|
||||||
|
#ifndef GLAD_API_CALL
|
||||||
|
#if defined(GLAD_API_CALL_EXPORT)
|
||||||
|
#if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
|
||||||
|
#if defined(GLAD_API_CALL_EXPORT_BUILD)
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define GLAD_API_CALL __attribute__ ((dllexport)) extern
|
||||||
|
#else
|
||||||
|
#define GLAD_API_CALL __declspec(dllexport) extern
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define GLAD_API_CALL __attribute__ ((dllimport)) extern
|
||||||
|
#else
|
||||||
|
#define GLAD_API_CALL __declspec(dllimport) extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
|
||||||
|
#define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
|
||||||
|
#else
|
||||||
|
#define GLAD_API_CALL extern
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define GLAD_API_CALL extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APIENTRY
|
||||||
|
#define GLAD_API_PTR APIENTRY
|
||||||
|
#elif GLAD_PLATFORM_WIN32
|
||||||
|
#define GLAD_API_PTR __stdcall
|
||||||
|
#else
|
||||||
|
#define GLAD_API_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAPI
|
||||||
|
#define GLAPI GLAD_API_CALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLAPIENTRY
|
||||||
|
#define GLAPIENTRY GLAD_API_PTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
|
||||||
|
#define GLAD_VERSION_MAJOR(version) (version / 10000)
|
||||||
|
#define GLAD_VERSION_MINOR(version) (version % 10000)
|
||||||
|
|
||||||
|
#define GLAD_GENERATOR_VERSION "2.0.8"
|
||||||
|
|
||||||
|
typedef void (*GLADapiproc)(void);
|
||||||
|
|
||||||
|
typedef GLADapiproc (*GLADloadfunc)(const char *name);
|
||||||
|
typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
|
||||||
|
|
||||||
|
typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
|
||||||
|
typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
|
||||||
|
|
||||||
|
#endif /* GLAD_PLATFORM_H_ */
|
||||||
|
|
||||||
|
#define EGL_ALPHA_FORMAT 0x3088
|
||||||
|
#define EGL_ALPHA_FORMAT_NONPRE 0x308B
|
||||||
|
#define EGL_ALPHA_FORMAT_PRE 0x308C
|
||||||
|
#define EGL_ALPHA_MASK_SIZE 0x303E
|
||||||
|
#define EGL_ALPHA_SIZE 0x3021
|
||||||
|
#define EGL_BACK_BUFFER 0x3084
|
||||||
|
#define EGL_BAD_ACCESS 0x3002
|
||||||
|
#define EGL_BAD_ALLOC 0x3003
|
||||||
|
#define EGL_BAD_ATTRIBUTE 0x3004
|
||||||
|
#define EGL_BAD_CONFIG 0x3005
|
||||||
|
#define EGL_BAD_CONTEXT 0x3006
|
||||||
|
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||||
|
#define EGL_BAD_DISPLAY 0x3008
|
||||||
|
#define EGL_BAD_MATCH 0x3009
|
||||||
|
#define EGL_BAD_NATIVE_PIXMAP 0x300A
|
||||||
|
#define EGL_BAD_NATIVE_WINDOW 0x300B
|
||||||
|
#define EGL_BAD_PARAMETER 0x300C
|
||||||
|
#define EGL_BAD_SURFACE 0x300D
|
||||||
|
#define EGL_BIND_TO_TEXTURE_RGB 0x3039
|
||||||
|
#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
|
||||||
|
#define EGL_BLUE_SIZE 0x3022
|
||||||
|
#define EGL_BUFFER_DESTROYED 0x3095
|
||||||
|
#define EGL_BUFFER_PRESERVED 0x3094
|
||||||
|
#define EGL_BUFFER_SIZE 0x3020
|
||||||
|
#define EGL_CLIENT_APIS 0x308D
|
||||||
|
#define EGL_CL_EVENT_HANDLE 0x309C
|
||||||
|
#define EGL_COLORSPACE 0x3087
|
||||||
|
#define EGL_COLORSPACE_LINEAR 0x308A
|
||||||
|
#define EGL_COLORSPACE_sRGB 0x3089
|
||||||
|
#define EGL_COLOR_BUFFER_TYPE 0x303F
|
||||||
|
#define EGL_CONDITION_SATISFIED 0x30F6
|
||||||
|
#define EGL_CONFIG_CAVEAT 0x3027
|
||||||
|
#define EGL_CONFIG_ID 0x3028
|
||||||
|
#define EGL_CONFORMANT 0x3042
|
||||||
|
#define EGL_CONTEXT_CLIENT_TYPE 0x3097
|
||||||
|
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||||
|
#define EGL_CONTEXT_LOST 0x300E
|
||||||
|
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
|
||||||
|
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
|
||||||
|
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||||
|
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
|
||||||
|
#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
|
||||||
|
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
|
||||||
|
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
|
||||||
|
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
|
||||||
|
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
|
||||||
|
#define EGL_CORE_NATIVE_ENGINE 0x305B
|
||||||
|
#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
|
||||||
|
#define EGL_DEPTH_SIZE 0x3025
|
||||||
|
#define EGL_DISPLAY_SCALING 10000
|
||||||
|
#define EGL_DONT_CARE EGL_CAST(EGLint,-1)
|
||||||
|
#define EGL_DRAW 0x3059
|
||||||
|
#define EGL_EXTENSIONS 0x3055
|
||||||
|
#define EGL_FALSE 0
|
||||||
|
#define EGL_FOREVER 0xFFFFFFFFFFFFFFFF
|
||||||
|
#define EGL_GL_COLORSPACE 0x309D
|
||||||
|
#define EGL_GL_COLORSPACE_LINEAR 0x308A
|
||||||
|
#define EGL_GL_COLORSPACE_SRGB 0x3089
|
||||||
|
#define EGL_GL_RENDERBUFFER 0x30B9
|
||||||
|
#define EGL_GL_TEXTURE_2D 0x30B1
|
||||||
|
#define EGL_GL_TEXTURE_3D 0x30B2
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
|
||||||
|
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
|
||||||
|
#define EGL_GL_TEXTURE_LEVEL 0x30BC
|
||||||
|
#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
|
||||||
|
#define EGL_GREEN_SIZE 0x3023
|
||||||
|
#define EGL_HEIGHT 0x3056
|
||||||
|
#define EGL_HORIZONTAL_RESOLUTION 0x3090
|
||||||
|
#define EGL_IMAGE_PRESERVED 0x30D2
|
||||||
|
#define EGL_LARGEST_PBUFFER 0x3058
|
||||||
|
#define EGL_LEVEL 0x3029
|
||||||
|
#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
|
||||||
|
#define EGL_LUMINANCE_BUFFER 0x308F
|
||||||
|
#define EGL_LUMINANCE_SIZE 0x303D
|
||||||
|
#define EGL_MATCH_NATIVE_PIXMAP 0x3041
|
||||||
|
#define EGL_MAX_PBUFFER_HEIGHT 0x302A
|
||||||
|
#define EGL_MAX_PBUFFER_PIXELS 0x302B
|
||||||
|
#define EGL_MAX_PBUFFER_WIDTH 0x302C
|
||||||
|
#define EGL_MAX_SWAP_INTERVAL 0x303C
|
||||||
|
#define EGL_MIN_SWAP_INTERVAL 0x303B
|
||||||
|
#define EGL_MIPMAP_LEVEL 0x3083
|
||||||
|
#define EGL_MIPMAP_TEXTURE 0x3082
|
||||||
|
#define EGL_MULTISAMPLE_RESOLVE 0x3099
|
||||||
|
#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
|
||||||
|
#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
|
||||||
|
#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
|
||||||
|
#define EGL_NATIVE_RENDERABLE 0x302D
|
||||||
|
#define EGL_NATIVE_VISUAL_ID 0x302E
|
||||||
|
#define EGL_NATIVE_VISUAL_TYPE 0x302F
|
||||||
|
#define EGL_NONE 0x3038
|
||||||
|
#define EGL_NON_CONFORMANT_CONFIG 0x3051
|
||||||
|
#define EGL_NOT_INITIALIZED 0x3001
|
||||||
|
#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0)
|
||||||
|
#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0)
|
||||||
|
#define EGL_NO_IMAGE EGL_CAST(EGLImage,0)
|
||||||
|
#define EGL_NO_RESET_NOTIFICATION 0x31BE
|
||||||
|
#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
|
||||||
|
#define EGL_NO_SYNC EGL_CAST(EGLSync,0)
|
||||||
|
#define EGL_NO_TEXTURE 0x305C
|
||||||
|
#define EGL_OPENGL_API 0x30A2
|
||||||
|
#define EGL_OPENGL_BIT 0x0008
|
||||||
|
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||||
|
#define EGL_OPENGL_ES3_BIT 0x00000040
|
||||||
|
#define EGL_OPENGL_ES_API 0x30A0
|
||||||
|
#define EGL_OPENGL_ES_BIT 0x0001
|
||||||
|
#define EGL_OPENVG_API 0x30A1
|
||||||
|
#define EGL_OPENVG_BIT 0x0002
|
||||||
|
#define EGL_OPENVG_IMAGE 0x3096
|
||||||
|
#define EGL_PBUFFER_BIT 0x0001
|
||||||
|
#define EGL_PIXEL_ASPECT_RATIO 0x3092
|
||||||
|
#define EGL_PIXMAP_BIT 0x0002
|
||||||
|
#define EGL_READ 0x305A
|
||||||
|
#define EGL_RED_SIZE 0x3024
|
||||||
|
#define EGL_RENDERABLE_TYPE 0x3040
|
||||||
|
#define EGL_RENDER_BUFFER 0x3086
|
||||||
|
#define EGL_RGB_BUFFER 0x308E
|
||||||
|
#define EGL_SAMPLES 0x3031
|
||||||
|
#define EGL_SAMPLE_BUFFERS 0x3032
|
||||||
|
#define EGL_SIGNALED 0x30F2
|
||||||
|
#define EGL_SINGLE_BUFFER 0x3085
|
||||||
|
#define EGL_SLOW_CONFIG 0x3050
|
||||||
|
#define EGL_STENCIL_SIZE 0x3026
|
||||||
|
#define EGL_SUCCESS 0x3000
|
||||||
|
#define EGL_SURFACE_TYPE 0x3033
|
||||||
|
#define EGL_SWAP_BEHAVIOR 0x3093
|
||||||
|
#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
|
||||||
|
#define EGL_SYNC_CL_EVENT 0x30FE
|
||||||
|
#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
|
||||||
|
#define EGL_SYNC_CONDITION 0x30F8
|
||||||
|
#define EGL_SYNC_FENCE 0x30F9
|
||||||
|
#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
|
||||||
|
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
|
||||||
|
#define EGL_SYNC_STATUS 0x30F1
|
||||||
|
#define EGL_SYNC_TYPE 0x30F7
|
||||||
|
#define EGL_TEXTURE_2D 0x305F
|
||||||
|
#define EGL_TEXTURE_FORMAT 0x3080
|
||||||
|
#define EGL_TEXTURE_RGB 0x305D
|
||||||
|
#define EGL_TEXTURE_RGBA 0x305E
|
||||||
|
#define EGL_TEXTURE_TARGET 0x3081
|
||||||
|
#define EGL_TIMEOUT_EXPIRED 0x30F5
|
||||||
|
#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
|
||||||
|
#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
|
||||||
|
#define EGL_TRANSPARENT_RED_VALUE 0x3037
|
||||||
|
#define EGL_TRANSPARENT_RGB 0x3052
|
||||||
|
#define EGL_TRANSPARENT_TYPE 0x3034
|
||||||
|
#define EGL_TRUE 1
|
||||||
|
#define EGL_UNKNOWN EGL_CAST(EGLint,-1)
|
||||||
|
#define EGL_UNSIGNALED 0x30F3
|
||||||
|
#define EGL_VENDOR 0x3053
|
||||||
|
#define EGL_VERSION 0x3054
|
||||||
|
#define EGL_VERTICAL_RESOLUTION 0x3091
|
||||||
|
#define EGL_VG_ALPHA_FORMAT 0x3088
|
||||||
|
#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
|
||||||
|
#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
|
||||||
|
#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
|
||||||
|
#define EGL_VG_COLORSPACE 0x3087
|
||||||
|
#define EGL_VG_COLORSPACE_LINEAR 0x308A
|
||||||
|
#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
|
||||||
|
#define EGL_VG_COLORSPACE_sRGB 0x3089
|
||||||
|
#define EGL_WIDTH 0x3057
|
||||||
|
#define EGL_WINDOW_BIT 0x0004
|
||||||
|
|
||||||
|
|
||||||
|
#include <KHR/khrplatform.h>
|
||||||
|
#include <EGL/eglplatform.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct AHardwareBuffer;
|
||||||
|
struct wl_buffer;
|
||||||
|
struct wl_display;
|
||||||
|
struct wl_resource;
|
||||||
|
|
||||||
|
typedef unsigned int EGLBoolean;
|
||||||
|
typedef unsigned int EGLenum;
|
||||||
|
typedef intptr_t EGLAttribKHR;
|
||||||
|
typedef intptr_t EGLAttrib;
|
||||||
|
typedef void *EGLClientBuffer;
|
||||||
|
typedef void *EGLConfig;
|
||||||
|
typedef void *EGLContext;
|
||||||
|
typedef void *EGLDeviceEXT;
|
||||||
|
typedef void *EGLDisplay;
|
||||||
|
typedef void *EGLImage;
|
||||||
|
typedef void *EGLImageKHR;
|
||||||
|
typedef void *EGLLabelKHR;
|
||||||
|
typedef void *EGLObjectKHR;
|
||||||
|
typedef void *EGLOutputLayerEXT;
|
||||||
|
typedef void *EGLOutputPortEXT;
|
||||||
|
typedef void *EGLStreamKHR;
|
||||||
|
typedef void *EGLSurface;
|
||||||
|
typedef void *EGLSync;
|
||||||
|
typedef void *EGLSyncKHR;
|
||||||
|
typedef void *EGLSyncNV;
|
||||||
|
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||||
|
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||||
|
typedef khronos_utime_nanoseconds_t EGLTime;
|
||||||
|
typedef khronos_utime_nanoseconds_t EGLTimeNV;
|
||||||
|
typedef khronos_utime_nanoseconds_t EGLuint64NV;
|
||||||
|
typedef khronos_uint64_t EGLuint64KHR;
|
||||||
|
typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
|
||||||
|
typedef int EGLNativeFileDescriptorKHR;
|
||||||
|
typedef khronos_ssize_t EGLsizeiANDROID;
|
||||||
|
typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
|
||||||
|
typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
|
||||||
|
struct EGLClientPixmapHI {
|
||||||
|
void *pData;
|
||||||
|
EGLint iWidth;
|
||||||
|
EGLint iHeight;
|
||||||
|
EGLint iStride;
|
||||||
|
};
|
||||||
|
typedef void (GLAD_API_PTR *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
|
||||||
|
#define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC
|
||||||
|
#define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC
|
||||||
|
#define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC
|
||||||
|
#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC
|
||||||
|
|
||||||
|
|
||||||
|
#define EGL_VERSION_1_0 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_0;
|
||||||
|
#define EGL_VERSION_1_1 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_1;
|
||||||
|
#define EGL_VERSION_1_2 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_2;
|
||||||
|
#define EGL_VERSION_1_3 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_3;
|
||||||
|
#define EGL_VERSION_1_4 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_4;
|
||||||
|
#define EGL_VERSION_1_5 1
|
||||||
|
GLAD_API_CALL int GLAD_EGL_VERSION_1_5;
|
||||||
|
|
||||||
|
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLBINDAPIPROC)(EGLenum api);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, const EGLint * attrib_list, EGLConfig * configs, EGLint config_size, EGLint * num_config);
|
||||||
|
typedef EGLint (GLAD_API_PTR *PFNEGLCLIENTWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLCOPYBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
|
||||||
|
typedef EGLContext (GLAD_API_PTR *PFNEGLCREATECONTEXTPROC)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint * attrib_list);
|
||||||
|
typedef EGLImage (GLAD_API_PTR *PFNEGLCREATEIMAGEPROC)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC)(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPBUFFERSURFACEPROC)(EGLDisplay dpy, EGLConfig config, const EGLint * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPIXMAPSURFACEPROC)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC)(EGLDisplay dpy, EGLConfig config, void * native_pixmap, const EGLAttrib * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEPLATFORMWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, void * native_window, const EGLAttrib * attrib_list);
|
||||||
|
typedef EGLSync (GLAD_API_PTR *PFNEGLCREATESYNCPROC)(EGLDisplay dpy, EGLenum type, const EGLAttrib * attrib_list);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint * attrib_list);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYIMAGEPROC)(EGLDisplay dpy, EGLImage image);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLDESTROYSYNCPROC)(EGLDisplay dpy, EGLSync sync);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint * value);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLGETCONFIGSPROC)(EGLDisplay dpy, EGLConfig * configs, EGLint config_size, EGLint * num_config);
|
||||||
|
typedef EGLContext (GLAD_API_PTR *PFNEGLGETCURRENTCONTEXTPROC)(void);
|
||||||
|
typedef EGLDisplay (GLAD_API_PTR *PFNEGLGETCURRENTDISPLAYPROC)(void);
|
||||||
|
typedef EGLSurface (GLAD_API_PTR *PFNEGLGETCURRENTSURFACEPROC)(EGLint readdraw);
|
||||||
|
typedef EGLDisplay (GLAD_API_PTR *PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType display_id);
|
||||||
|
typedef EGLint (GLAD_API_PTR *PFNEGLGETERRORPROC)(void);
|
||||||
|
typedef EGLDisplay (GLAD_API_PTR *PFNEGLGETPLATFORMDISPLAYPROC)(EGLenum platform, void * native_display, const EGLAttrib * attrib_list);
|
||||||
|
typedef __eglMustCastToProperFunctionPointerType (GLAD_API_PTR *PFNEGLGETPROCADDRESSPROC)(const char * procname);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLGETSYNCATTRIBPROC)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib * value);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLINITIALIZEPROC)(EGLDisplay dpy, EGLint * major, EGLint * minor);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLMAKECURRENTPROC)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||||
|
typedef EGLenum (GLAD_API_PTR *PFNEGLQUERYAPIPROC)(void);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYCONTEXTPROC)(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint * value);
|
||||||
|
typedef const char * (GLAD_API_PTR *PFNEGLQUERYSTRINGPROC)(EGLDisplay dpy, EGLint name);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLQUERYSURFACEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint * value);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLRELEASETEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLRELEASETHREADPROC)(void);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLSURFACEATTRIBPROC)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLSWAPBUFFERSPROC)(EGLDisplay dpy, EGLSurface surface);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLSWAPINTERVALPROC)(EGLDisplay dpy, EGLint interval);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLTERMINATEPROC)(EGLDisplay dpy);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLWAITCLIENTPROC)(void);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLWAITGLPROC)(void);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLWAITNATIVEPROC)(EGLint engine);
|
||||||
|
typedef EGLBoolean (GLAD_API_PTR *PFNEGLWAITSYNCPROC)(EGLDisplay dpy, EGLSync sync, EGLint flags);
|
||||||
|
|
||||||
|
GLAD_API_CALL PFNEGLBINDAPIPROC glad_eglBindAPI;
|
||||||
|
#define eglBindAPI glad_eglBindAPI
|
||||||
|
GLAD_API_CALL PFNEGLBINDTEXIMAGEPROC glad_eglBindTexImage;
|
||||||
|
#define eglBindTexImage glad_eglBindTexImage
|
||||||
|
GLAD_API_CALL PFNEGLCHOOSECONFIGPROC glad_eglChooseConfig;
|
||||||
|
#define eglChooseConfig glad_eglChooseConfig
|
||||||
|
GLAD_API_CALL PFNEGLCLIENTWAITSYNCPROC glad_eglClientWaitSync;
|
||||||
|
#define eglClientWaitSync glad_eglClientWaitSync
|
||||||
|
GLAD_API_CALL PFNEGLCOPYBUFFERSPROC glad_eglCopyBuffers;
|
||||||
|
#define eglCopyBuffers glad_eglCopyBuffers
|
||||||
|
GLAD_API_CALL PFNEGLCREATECONTEXTPROC glad_eglCreateContext;
|
||||||
|
#define eglCreateContext glad_eglCreateContext
|
||||||
|
GLAD_API_CALL PFNEGLCREATEIMAGEPROC glad_eglCreateImage;
|
||||||
|
#define eglCreateImage glad_eglCreateImage
|
||||||
|
GLAD_API_CALL PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC glad_eglCreatePbufferFromClientBuffer;
|
||||||
|
#define eglCreatePbufferFromClientBuffer glad_eglCreatePbufferFromClientBuffer
|
||||||
|
GLAD_API_CALL PFNEGLCREATEPBUFFERSURFACEPROC glad_eglCreatePbufferSurface;
|
||||||
|
#define eglCreatePbufferSurface glad_eglCreatePbufferSurface
|
||||||
|
GLAD_API_CALL PFNEGLCREATEPIXMAPSURFACEPROC glad_eglCreatePixmapSurface;
|
||||||
|
#define eglCreatePixmapSurface glad_eglCreatePixmapSurface
|
||||||
|
GLAD_API_CALL PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC glad_eglCreatePlatformPixmapSurface;
|
||||||
|
#define eglCreatePlatformPixmapSurface glad_eglCreatePlatformPixmapSurface
|
||||||
|
GLAD_API_CALL PFNEGLCREATEPLATFORMWINDOWSURFACEPROC glad_eglCreatePlatformWindowSurface;
|
||||||
|
#define eglCreatePlatformWindowSurface glad_eglCreatePlatformWindowSurface
|
||||||
|
GLAD_API_CALL PFNEGLCREATESYNCPROC glad_eglCreateSync;
|
||||||
|
#define eglCreateSync glad_eglCreateSync
|
||||||
|
GLAD_API_CALL PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface;
|
||||||
|
#define eglCreateWindowSurface glad_eglCreateWindowSurface
|
||||||
|
GLAD_API_CALL PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext;
|
||||||
|
#define eglDestroyContext glad_eglDestroyContext
|
||||||
|
GLAD_API_CALL PFNEGLDESTROYIMAGEPROC glad_eglDestroyImage;
|
||||||
|
#define eglDestroyImage glad_eglDestroyImage
|
||||||
|
GLAD_API_CALL PFNEGLDESTROYSURFACEPROC glad_eglDestroySurface;
|
||||||
|
#define eglDestroySurface glad_eglDestroySurface
|
||||||
|
GLAD_API_CALL PFNEGLDESTROYSYNCPROC glad_eglDestroySync;
|
||||||
|
#define eglDestroySync glad_eglDestroySync
|
||||||
|
GLAD_API_CALL PFNEGLGETCONFIGATTRIBPROC glad_eglGetConfigAttrib;
|
||||||
|
#define eglGetConfigAttrib glad_eglGetConfigAttrib
|
||||||
|
GLAD_API_CALL PFNEGLGETCONFIGSPROC glad_eglGetConfigs;
|
||||||
|
#define eglGetConfigs glad_eglGetConfigs
|
||||||
|
GLAD_API_CALL PFNEGLGETCURRENTCONTEXTPROC glad_eglGetCurrentContext;
|
||||||
|
#define eglGetCurrentContext glad_eglGetCurrentContext
|
||||||
|
GLAD_API_CALL PFNEGLGETCURRENTDISPLAYPROC glad_eglGetCurrentDisplay;
|
||||||
|
#define eglGetCurrentDisplay glad_eglGetCurrentDisplay
|
||||||
|
GLAD_API_CALL PFNEGLGETCURRENTSURFACEPROC glad_eglGetCurrentSurface;
|
||||||
|
#define eglGetCurrentSurface glad_eglGetCurrentSurface
|
||||||
|
GLAD_API_CALL PFNEGLGETDISPLAYPROC glad_eglGetDisplay;
|
||||||
|
#define eglGetDisplay glad_eglGetDisplay
|
||||||
|
GLAD_API_CALL PFNEGLGETERRORPROC glad_eglGetError;
|
||||||
|
#define eglGetError glad_eglGetError
|
||||||
|
GLAD_API_CALL PFNEGLGETPLATFORMDISPLAYPROC glad_eglGetPlatformDisplay;
|
||||||
|
#define eglGetPlatformDisplay glad_eglGetPlatformDisplay
|
||||||
|
GLAD_API_CALL PFNEGLGETPROCADDRESSPROC glad_eglGetProcAddress;
|
||||||
|
#define eglGetProcAddress glad_eglGetProcAddress
|
||||||
|
GLAD_API_CALL PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib;
|
||||||
|
#define eglGetSyncAttrib glad_eglGetSyncAttrib
|
||||||
|
GLAD_API_CALL PFNEGLINITIALIZEPROC glad_eglInitialize;
|
||||||
|
#define eglInitialize glad_eglInitialize
|
||||||
|
GLAD_API_CALL PFNEGLMAKECURRENTPROC glad_eglMakeCurrent;
|
||||||
|
#define eglMakeCurrent glad_eglMakeCurrent
|
||||||
|
GLAD_API_CALL PFNEGLQUERYAPIPROC glad_eglQueryAPI;
|
||||||
|
#define eglQueryAPI glad_eglQueryAPI
|
||||||
|
GLAD_API_CALL PFNEGLQUERYCONTEXTPROC glad_eglQueryContext;
|
||||||
|
#define eglQueryContext glad_eglQueryContext
|
||||||
|
GLAD_API_CALL PFNEGLQUERYSTRINGPROC glad_eglQueryString;
|
||||||
|
#define eglQueryString glad_eglQueryString
|
||||||
|
GLAD_API_CALL PFNEGLQUERYSURFACEPROC glad_eglQuerySurface;
|
||||||
|
#define eglQuerySurface glad_eglQuerySurface
|
||||||
|
GLAD_API_CALL PFNEGLRELEASETEXIMAGEPROC glad_eglReleaseTexImage;
|
||||||
|
#define eglReleaseTexImage glad_eglReleaseTexImage
|
||||||
|
GLAD_API_CALL PFNEGLRELEASETHREADPROC glad_eglReleaseThread;
|
||||||
|
#define eglReleaseThread glad_eglReleaseThread
|
||||||
|
GLAD_API_CALL PFNEGLSURFACEATTRIBPROC glad_eglSurfaceAttrib;
|
||||||
|
#define eglSurfaceAttrib glad_eglSurfaceAttrib
|
||||||
|
GLAD_API_CALL PFNEGLSWAPBUFFERSPROC glad_eglSwapBuffers;
|
||||||
|
#define eglSwapBuffers glad_eglSwapBuffers
|
||||||
|
GLAD_API_CALL PFNEGLSWAPINTERVALPROC glad_eglSwapInterval;
|
||||||
|
#define eglSwapInterval glad_eglSwapInterval
|
||||||
|
GLAD_API_CALL PFNEGLTERMINATEPROC glad_eglTerminate;
|
||||||
|
#define eglTerminate glad_eglTerminate
|
||||||
|
GLAD_API_CALL PFNEGLWAITCLIENTPROC glad_eglWaitClient;
|
||||||
|
#define eglWaitClient glad_eglWaitClient
|
||||||
|
GLAD_API_CALL PFNEGLWAITGLPROC glad_eglWaitGL;
|
||||||
|
#define eglWaitGL glad_eglWaitGL
|
||||||
|
GLAD_API_CALL PFNEGLWAITNATIVEPROC glad_eglWaitNative;
|
||||||
|
#define eglWaitNative glad_eglWaitNative
|
||||||
|
GLAD_API_CALL PFNEGLWAITSYNCPROC glad_eglWaitSync;
|
||||||
|
#define eglWaitSync glad_eglWaitSync
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLAD_API_CALL int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void *userptr);
|
||||||
|
GLAD_API_CALL int gladLoadEGL(EGLDisplay display, GLADloadfunc load);
|
||||||
|
|
||||||
|
#ifdef GLAD_EGL
|
||||||
|
|
||||||
|
GLAD_API_CALL int gladLoaderLoadEGL(EGLDisplay display);
|
||||||
|
|
||||||
|
GLAD_API_CALL void gladLoaderUnloadEGL(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
3644
external/glad/include/glad/gl.h
vendored
Normal file
397
external/glad/src/egl.c
vendored
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/**
|
||||||
|
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <glad/egl.h>
|
||||||
|
|
||||||
|
#ifndef GLAD_IMPL_UTIL_C_
|
||||||
|
#define GLAD_IMPL_UTIL_C_
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define GLAD_IMPL_UTIL_SSCANF sscanf_s
|
||||||
|
#else
|
||||||
|
#define GLAD_IMPL_UTIL_SSCANF sscanf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GLAD_IMPL_UTIL_C_ */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int GLAD_EGL_VERSION_1_0 = 0;
|
||||||
|
int GLAD_EGL_VERSION_1_1 = 0;
|
||||||
|
int GLAD_EGL_VERSION_1_2 = 0;
|
||||||
|
int GLAD_EGL_VERSION_1_3 = 0;
|
||||||
|
int GLAD_EGL_VERSION_1_4 = 0;
|
||||||
|
int GLAD_EGL_VERSION_1_5 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PFNEGLBINDAPIPROC glad_eglBindAPI = NULL;
|
||||||
|
PFNEGLBINDTEXIMAGEPROC glad_eglBindTexImage = NULL;
|
||||||
|
PFNEGLCHOOSECONFIGPROC glad_eglChooseConfig = NULL;
|
||||||
|
PFNEGLCLIENTWAITSYNCPROC glad_eglClientWaitSync = NULL;
|
||||||
|
PFNEGLCOPYBUFFERSPROC glad_eglCopyBuffers = NULL;
|
||||||
|
PFNEGLCREATECONTEXTPROC glad_eglCreateContext = NULL;
|
||||||
|
PFNEGLCREATEIMAGEPROC glad_eglCreateImage = NULL;
|
||||||
|
PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC glad_eglCreatePbufferFromClientBuffer = NULL;
|
||||||
|
PFNEGLCREATEPBUFFERSURFACEPROC glad_eglCreatePbufferSurface = NULL;
|
||||||
|
PFNEGLCREATEPIXMAPSURFACEPROC glad_eglCreatePixmapSurface = NULL;
|
||||||
|
PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC glad_eglCreatePlatformPixmapSurface = NULL;
|
||||||
|
PFNEGLCREATEPLATFORMWINDOWSURFACEPROC glad_eglCreatePlatformWindowSurface = NULL;
|
||||||
|
PFNEGLCREATESYNCPROC glad_eglCreateSync = NULL;
|
||||||
|
PFNEGLCREATEWINDOWSURFACEPROC glad_eglCreateWindowSurface = NULL;
|
||||||
|
PFNEGLDESTROYCONTEXTPROC glad_eglDestroyContext = NULL;
|
||||||
|
PFNEGLDESTROYIMAGEPROC glad_eglDestroyImage = NULL;
|
||||||
|
PFNEGLDESTROYSURFACEPROC glad_eglDestroySurface = NULL;
|
||||||
|
PFNEGLDESTROYSYNCPROC glad_eglDestroySync = NULL;
|
||||||
|
PFNEGLGETCONFIGATTRIBPROC glad_eglGetConfigAttrib = NULL;
|
||||||
|
PFNEGLGETCONFIGSPROC glad_eglGetConfigs = NULL;
|
||||||
|
PFNEGLGETCURRENTCONTEXTPROC glad_eglGetCurrentContext = NULL;
|
||||||
|
PFNEGLGETCURRENTDISPLAYPROC glad_eglGetCurrentDisplay = NULL;
|
||||||
|
PFNEGLGETCURRENTSURFACEPROC glad_eglGetCurrentSurface = NULL;
|
||||||
|
PFNEGLGETDISPLAYPROC glad_eglGetDisplay = NULL;
|
||||||
|
PFNEGLGETERRORPROC glad_eglGetError = NULL;
|
||||||
|
PFNEGLGETPLATFORMDISPLAYPROC glad_eglGetPlatformDisplay = NULL;
|
||||||
|
PFNEGLGETPROCADDRESSPROC glad_eglGetProcAddress = NULL;
|
||||||
|
PFNEGLGETSYNCATTRIBPROC glad_eglGetSyncAttrib = NULL;
|
||||||
|
PFNEGLINITIALIZEPROC glad_eglInitialize = NULL;
|
||||||
|
PFNEGLMAKECURRENTPROC glad_eglMakeCurrent = NULL;
|
||||||
|
PFNEGLQUERYAPIPROC glad_eglQueryAPI = NULL;
|
||||||
|
PFNEGLQUERYCONTEXTPROC glad_eglQueryContext = NULL;
|
||||||
|
PFNEGLQUERYSTRINGPROC glad_eglQueryString = NULL;
|
||||||
|
PFNEGLQUERYSURFACEPROC glad_eglQuerySurface = NULL;
|
||||||
|
PFNEGLRELEASETEXIMAGEPROC glad_eglReleaseTexImage = NULL;
|
||||||
|
PFNEGLRELEASETHREADPROC glad_eglReleaseThread = NULL;
|
||||||
|
PFNEGLSURFACEATTRIBPROC glad_eglSurfaceAttrib = NULL;
|
||||||
|
PFNEGLSWAPBUFFERSPROC glad_eglSwapBuffers = NULL;
|
||||||
|
PFNEGLSWAPINTERVALPROC glad_eglSwapInterval = NULL;
|
||||||
|
PFNEGLTERMINATEPROC glad_eglTerminate = NULL;
|
||||||
|
PFNEGLWAITCLIENTPROC glad_eglWaitClient = NULL;
|
||||||
|
PFNEGLWAITGLPROC glad_eglWaitGL = NULL;
|
||||||
|
PFNEGLWAITNATIVEPROC glad_eglWaitNative = NULL;
|
||||||
|
PFNEGLWAITSYNCPROC glad_eglWaitSync = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void glad_egl_load_EGL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_EGL_VERSION_1_0) return;
|
||||||
|
glad_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) load(userptr, "eglChooseConfig");
|
||||||
|
glad_eglCopyBuffers = (PFNEGLCOPYBUFFERSPROC) load(userptr, "eglCopyBuffers");
|
||||||
|
glad_eglCreateContext = (PFNEGLCREATECONTEXTPROC) load(userptr, "eglCreateContext");
|
||||||
|
glad_eglCreatePbufferSurface = (PFNEGLCREATEPBUFFERSURFACEPROC) load(userptr, "eglCreatePbufferSurface");
|
||||||
|
glad_eglCreatePixmapSurface = (PFNEGLCREATEPIXMAPSURFACEPROC) load(userptr, "eglCreatePixmapSurface");
|
||||||
|
glad_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) load(userptr, "eglCreateWindowSurface");
|
||||||
|
glad_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) load(userptr, "eglDestroyContext");
|
||||||
|
glad_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) load(userptr, "eglDestroySurface");
|
||||||
|
glad_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) load(userptr, "eglGetConfigAttrib");
|
||||||
|
glad_eglGetConfigs = (PFNEGLGETCONFIGSPROC) load(userptr, "eglGetConfigs");
|
||||||
|
glad_eglGetCurrentDisplay = (PFNEGLGETCURRENTDISPLAYPROC) load(userptr, "eglGetCurrentDisplay");
|
||||||
|
glad_eglGetCurrentSurface = (PFNEGLGETCURRENTSURFACEPROC) load(userptr, "eglGetCurrentSurface");
|
||||||
|
glad_eglGetDisplay = (PFNEGLGETDISPLAYPROC) load(userptr, "eglGetDisplay");
|
||||||
|
glad_eglGetError = (PFNEGLGETERRORPROC) load(userptr, "eglGetError");
|
||||||
|
glad_eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC) load(userptr, "eglGetProcAddress");
|
||||||
|
glad_eglInitialize = (PFNEGLINITIALIZEPROC) load(userptr, "eglInitialize");
|
||||||
|
glad_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) load(userptr, "eglMakeCurrent");
|
||||||
|
glad_eglQueryContext = (PFNEGLQUERYCONTEXTPROC) load(userptr, "eglQueryContext");
|
||||||
|
glad_eglQueryString = (PFNEGLQUERYSTRINGPROC) load(userptr, "eglQueryString");
|
||||||
|
glad_eglQuerySurface = (PFNEGLQUERYSURFACEPROC) load(userptr, "eglQuerySurface");
|
||||||
|
glad_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) load(userptr, "eglSwapBuffers");
|
||||||
|
glad_eglTerminate = (PFNEGLTERMINATEPROC) load(userptr, "eglTerminate");
|
||||||
|
glad_eglWaitGL = (PFNEGLWAITGLPROC) load(userptr, "eglWaitGL");
|
||||||
|
glad_eglWaitNative = (PFNEGLWAITNATIVEPROC) load(userptr, "eglWaitNative");
|
||||||
|
}
|
||||||
|
static void glad_egl_load_EGL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_EGL_VERSION_1_1) return;
|
||||||
|
glad_eglBindTexImage = (PFNEGLBINDTEXIMAGEPROC) load(userptr, "eglBindTexImage");
|
||||||
|
glad_eglReleaseTexImage = (PFNEGLRELEASETEXIMAGEPROC) load(userptr, "eglReleaseTexImage");
|
||||||
|
glad_eglSurfaceAttrib = (PFNEGLSURFACEATTRIBPROC) load(userptr, "eglSurfaceAttrib");
|
||||||
|
glad_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) load(userptr, "eglSwapInterval");
|
||||||
|
}
|
||||||
|
static void glad_egl_load_EGL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_EGL_VERSION_1_2) return;
|
||||||
|
glad_eglBindAPI = (PFNEGLBINDAPIPROC) load(userptr, "eglBindAPI");
|
||||||
|
glad_eglCreatePbufferFromClientBuffer = (PFNEGLCREATEPBUFFERFROMCLIENTBUFFERPROC) load(userptr, "eglCreatePbufferFromClientBuffer");
|
||||||
|
glad_eglQueryAPI = (PFNEGLQUERYAPIPROC) load(userptr, "eglQueryAPI");
|
||||||
|
glad_eglReleaseThread = (PFNEGLRELEASETHREADPROC) load(userptr, "eglReleaseThread");
|
||||||
|
glad_eglWaitClient = (PFNEGLWAITCLIENTPROC) load(userptr, "eglWaitClient");
|
||||||
|
}
|
||||||
|
static void glad_egl_load_EGL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_EGL_VERSION_1_4) return;
|
||||||
|
glad_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) load(userptr, "eglGetCurrentContext");
|
||||||
|
}
|
||||||
|
static void glad_egl_load_EGL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_EGL_VERSION_1_5) return;
|
||||||
|
glad_eglClientWaitSync = (PFNEGLCLIENTWAITSYNCPROC) load(userptr, "eglClientWaitSync");
|
||||||
|
glad_eglCreateImage = (PFNEGLCREATEIMAGEPROC) load(userptr, "eglCreateImage");
|
||||||
|
glad_eglCreatePlatformPixmapSurface = (PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC) load(userptr, "eglCreatePlatformPixmapSurface");
|
||||||
|
glad_eglCreatePlatformWindowSurface = (PFNEGLCREATEPLATFORMWINDOWSURFACEPROC) load(userptr, "eglCreatePlatformWindowSurface");
|
||||||
|
glad_eglCreateSync = (PFNEGLCREATESYNCPROC) load(userptr, "eglCreateSync");
|
||||||
|
glad_eglDestroyImage = (PFNEGLDESTROYIMAGEPROC) load(userptr, "eglDestroyImage");
|
||||||
|
glad_eglDestroySync = (PFNEGLDESTROYSYNCPROC) load(userptr, "eglDestroySync");
|
||||||
|
glad_eglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYPROC) load(userptr, "eglGetPlatformDisplay");
|
||||||
|
glad_eglGetSyncAttrib = (PFNEGLGETSYNCATTRIBPROC) load(userptr, "eglGetSyncAttrib");
|
||||||
|
glad_eglWaitSync = (PFNEGLWAITSYNCPROC) load(userptr, "eglWaitSync");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int glad_egl_get_extensions(EGLDisplay display, const char **extensions) {
|
||||||
|
*extensions = eglQueryString(display, EGL_EXTENSIONS);
|
||||||
|
|
||||||
|
return extensions != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int glad_egl_has_extension(const char *extensions, const char *ext) {
|
||||||
|
const char *loc;
|
||||||
|
const char *terminator;
|
||||||
|
if(extensions == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(1) {
|
||||||
|
loc = strstr(extensions, ext);
|
||||||
|
if(loc == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
terminator = loc + strlen(ext);
|
||||||
|
if((loc == extensions || *(loc - 1) == ' ') &&
|
||||||
|
(*terminator == ' ' || *terminator == '\0')) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
extensions = terminator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLADapiproc glad_egl_get_proc_from_userptr(void *userptr, const char *name) {
|
||||||
|
return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int glad_egl_find_extensions_egl(EGLDisplay display) {
|
||||||
|
const char *extensions;
|
||||||
|
if (!glad_egl_get_extensions(display, &extensions)) return 0;
|
||||||
|
|
||||||
|
GLAD_UNUSED(&glad_egl_has_extension);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int glad_egl_find_core_egl(EGLDisplay display) {
|
||||||
|
int major, minor;
|
||||||
|
const char *version;
|
||||||
|
|
||||||
|
if (display == NULL) {
|
||||||
|
display = EGL_NO_DISPLAY; /* this is usually NULL, better safe than sorry */
|
||||||
|
}
|
||||||
|
if (display == EGL_NO_DISPLAY) {
|
||||||
|
display = eglGetCurrentDisplay();
|
||||||
|
}
|
||||||
|
#ifdef EGL_VERSION_1_4
|
||||||
|
if (display == EGL_NO_DISPLAY) {
|
||||||
|
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef EGL_VERSION_1_5
|
||||||
|
if (display == EGL_NO_DISPLAY) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
version = eglQueryString(display, EGL_VERSION);
|
||||||
|
(void) eglGetError();
|
||||||
|
|
||||||
|
if (version == NULL) {
|
||||||
|
major = 1;
|
||||||
|
minor = 0;
|
||||||
|
} else {
|
||||||
|
GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLAD_EGL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
|
||||||
|
GLAD_EGL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
|
||||||
|
GLAD_EGL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
|
||||||
|
GLAD_EGL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
|
||||||
|
GLAD_EGL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
|
||||||
|
GLAD_EGL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
|
||||||
|
|
||||||
|
return GLAD_MAKE_VERSION(major, minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
int version;
|
||||||
|
eglGetDisplay = (PFNEGLGETDISPLAYPROC) load(userptr, "eglGetDisplay");
|
||||||
|
eglGetCurrentDisplay = (PFNEGLGETCURRENTDISPLAYPROC) load(userptr, "eglGetCurrentDisplay");
|
||||||
|
eglQueryString = (PFNEGLQUERYSTRINGPROC) load(userptr, "eglQueryString");
|
||||||
|
eglGetError = (PFNEGLGETERRORPROC) load(userptr, "eglGetError");
|
||||||
|
if (eglGetDisplay == NULL || eglGetCurrentDisplay == NULL || eglQueryString == NULL || eglGetError == NULL) return 0;
|
||||||
|
|
||||||
|
version = glad_egl_find_core_egl(display);
|
||||||
|
if (!version) return 0;
|
||||||
|
glad_egl_load_EGL_VERSION_1_0(load, userptr);
|
||||||
|
glad_egl_load_EGL_VERSION_1_1(load, userptr);
|
||||||
|
glad_egl_load_EGL_VERSION_1_2(load, userptr);
|
||||||
|
glad_egl_load_EGL_VERSION_1_4(load, userptr);
|
||||||
|
glad_egl_load_EGL_VERSION_1_5(load, userptr);
|
||||||
|
|
||||||
|
if (!glad_egl_find_extensions_egl(display)) return 0;
|
||||||
|
|
||||||
|
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gladLoadEGL(EGLDisplay display, GLADloadfunc load) {
|
||||||
|
return gladLoadEGLUserPtr(display, glad_egl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GLAD_EGL
|
||||||
|
|
||||||
|
#ifndef GLAD_LOADER_LIBRARY_C_
|
||||||
|
#define GLAD_LOADER_LIBRARY_C_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if GLAD_PLATFORM_WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void* glad_get_dlopen_handle(const char *lib_names[], int length) {
|
||||||
|
void *handle = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
#if GLAD_PLATFORM_WIN32
|
||||||
|
#if GLAD_PLATFORM_UWP
|
||||||
|
size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR);
|
||||||
|
LPWSTR buffer = (LPWSTR) malloc(buffer_size);
|
||||||
|
if (buffer != NULL) {
|
||||||
|
int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size);
|
||||||
|
if (ret != 0) {
|
||||||
|
handle = (void*) LoadPackagedLibrary(buffer, 0);
|
||||||
|
}
|
||||||
|
free((void*) buffer);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
handle = (void*) LoadLibraryA(lib_names[i]);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
#endif
|
||||||
|
if (handle != NULL) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glad_close_dlopen_handle(void* handle) {
|
||||||
|
if (handle != NULL) {
|
||||||
|
#if GLAD_PLATFORM_WIN32
|
||||||
|
FreeLibrary((HMODULE) handle);
|
||||||
|
#else
|
||||||
|
dlclose(handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLADapiproc glad_dlsym_handle(void* handle, const char *name) {
|
||||||
|
if (handle == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GLAD_PLATFORM_WIN32
|
||||||
|
return (GLADapiproc) GetProcAddress((HMODULE) handle, name);
|
||||||
|
#else
|
||||||
|
return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GLAD_LOADER_LIBRARY_C_ */
|
||||||
|
|
||||||
|
struct _glad_egl_userptr {
|
||||||
|
void *handle;
|
||||||
|
PFNEGLGETPROCADDRESSPROC get_proc_address_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLADapiproc glad_egl_get_proc(void *vuserptr, const char* name) {
|
||||||
|
struct _glad_egl_userptr userptr = *(struct _glad_egl_userptr*) vuserptr;
|
||||||
|
GLADapiproc result = NULL;
|
||||||
|
|
||||||
|
result = glad_dlsym_handle(userptr.handle, name);
|
||||||
|
if (result == NULL) {
|
||||||
|
result = GLAD_GNUC_EXTENSION (GLADapiproc) userptr.get_proc_address_ptr(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* _egl_handle = NULL;
|
||||||
|
|
||||||
|
static void* glad_egl_dlopen_handle(void) {
|
||||||
|
#if GLAD_PLATFORM_APPLE
|
||||||
|
static const char *NAMES[] = {"libEGL.dylib"};
|
||||||
|
#elif GLAD_PLATFORM_WIN32
|
||||||
|
static const char *NAMES[] = {"libEGL.dll", "EGL.dll"};
|
||||||
|
#else
|
||||||
|
static const char *NAMES[] = {"libEGL.so.1", "libEGL.so"};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_egl_handle == NULL) {
|
||||||
|
_egl_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _egl_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct _glad_egl_userptr glad_egl_build_userptr(void *handle) {
|
||||||
|
struct _glad_egl_userptr userptr;
|
||||||
|
userptr.handle = handle;
|
||||||
|
userptr.get_proc_address_ptr = (PFNEGLGETPROCADDRESSPROC) glad_dlsym_handle(handle, "eglGetProcAddress");
|
||||||
|
return userptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gladLoaderLoadEGL(EGLDisplay display) {
|
||||||
|
int version = 0;
|
||||||
|
void *handle = NULL;
|
||||||
|
int did_load = 0;
|
||||||
|
struct _glad_egl_userptr userptr;
|
||||||
|
|
||||||
|
did_load = _egl_handle == NULL;
|
||||||
|
handle = glad_egl_dlopen_handle();
|
||||||
|
if (handle != NULL) {
|
||||||
|
userptr = glad_egl_build_userptr(handle);
|
||||||
|
|
||||||
|
if (userptr.get_proc_address_ptr != NULL) {
|
||||||
|
version = gladLoadEGLUserPtr(display, glad_egl_get_proc, &userptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!version && did_load) {
|
||||||
|
gladLoaderUnloadEGL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gladLoaderUnloadEGL(void) {
|
||||||
|
if (_egl_handle != NULL) {
|
||||||
|
glad_close_dlopen_handle(_egl_handle);
|
||||||
|
_egl_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GLAD_EGL */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
1786
external/glad/src/gl.c
vendored
Normal file
6574
external/m3d/m3d.h
vendored
Normal file
10838
external/rgfw/RGFW.h
vendored
Normal file
7988
external/stb/stb_image.h
vendored
Normal file
1906
external/stb/stb_sprintf.h
vendored
Normal file
26
external/xxhash/LICENSE
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
xxHash Library
|
||||||
|
Copyright (c) 2012-2021 Yann Collet
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
274
external/xxhash/README.md
vendored
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
|
||||||
|
xxHash - Extremely fast hash algorithm
|
||||||
|
======================================
|
||||||
|
|
||||||
|
xxHash is an Extremely fast Hash algorithm, processing at RAM speed limits.
|
||||||
|
Code is highly portable, and produces hashes identical across all platforms (little / big endian).
|
||||||
|
The library includes the following algorithms :
|
||||||
|
- XXH32 : generates 32-bit hashes, using 32-bit arithmetic
|
||||||
|
- XXH64 : generates 64-bit hashes, using 64-bit arithmetic
|
||||||
|
- XXH3 (since `v0.8.0`): generates 64 or 128-bit hashes, using vectorized arithmetic.
|
||||||
|
The 128-bit variant is called XXH128.
|
||||||
|
|
||||||
|
All variants successfully complete the [SMHasher](https://code.google.com/p/smhasher/wiki/SMHasher) test suite
|
||||||
|
which evaluates the quality of hash functions (collision, dispersion and randomness).
|
||||||
|
Additional tests, which evaluate more thoroughly speed and collision properties of 64-bit hashes, [are also provided](https://github.com/Cyan4973/xxHash/tree/dev/tests).
|
||||||
|
|
||||||
|
|Branch |Status |
|
||||||
|
|------------|---------|
|
||||||
|
|release | [](https://github.com/Cyan4973/xxHash/actions?query=branch%3Arelease+) |
|
||||||
|
|dev | [](https://github.com/Cyan4973/xxHash/actions?query=branch%3Adev+) |
|
||||||
|
|
||||||
|
|
||||||
|
Benchmarks
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The benchmarked reference system uses an Intel i7-9700K cpu, and runs Ubuntu x64 20.04.
|
||||||
|
The [open source benchmark program] is compiled with `clang` v10.0 using `-O3` flag.
|
||||||
|
|
||||||
|
| Hash Name | Width | Bandwidth (GB/s) | Small Data Velocity | Quality | Comment |
|
||||||
|
| --------- | ----- | ---------------- | ----- | --- | --- |
|
||||||
|
| __XXH3__ (SSE2) | 64 | 31.5 GB/s | 133.1 | 10
|
||||||
|
| __XXH128__ (SSE2) | 128 | 29.6 GB/s | 118.1 | 10
|
||||||
|
| _RAM sequential read_ | N/A | 28.0 GB/s | N/A | N/A | _for reference_
|
||||||
|
| City64 | 64 | 22.0 GB/s | 76.6 | 10
|
||||||
|
| T1ha2 | 64 | 22.0 GB/s | 99.0 | 9 | Slightly worse [collisions]
|
||||||
|
| City128 | 128 | 21.7 GB/s | 57.7 | 10
|
||||||
|
| __XXH64__ | 64 | 19.4 GB/s | 71.0 | 10
|
||||||
|
| SpookyHash | 64 | 19.3 GB/s | 53.2 | 10
|
||||||
|
| Mum | 64 | 18.0 GB/s | 67.0 | 9 | Slightly worse [collisions]
|
||||||
|
| __XXH32__ | 32 | 9.7 GB/s | 71.9 | 10
|
||||||
|
| City32 | 32 | 9.1 GB/s | 66.0 | 10
|
||||||
|
| Murmur3 | 32 | 3.9 GB/s | 56.1 | 10
|
||||||
|
| SipHash | 64 | 3.0 GB/s | 43.2 | 10
|
||||||
|
| FNV64 | 64 | 1.2 GB/s | 62.7 | 5 | Poor avalanche properties
|
||||||
|
| Blake2 | 256 | 1.1 GB/s | 5.1 | 10 | Cryptographic
|
||||||
|
| SHA1 | 160 | 0.8 GB/s | 5.6 | 10 | Cryptographic but broken
|
||||||
|
| MD5 | 128 | 0.6 GB/s | 7.8 | 10 | Cryptographic but broken
|
||||||
|
|
||||||
|
[open source benchmark program]: https://github.com/Cyan4973/xxHash/tree/release/tests/bench
|
||||||
|
[collisions]: https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison#collision-study
|
||||||
|
|
||||||
|
note 1: Small data velocity is a _rough_ evaluation of algorithm's efficiency on small data. For more detailed analysis, please refer to next paragraph.
|
||||||
|
|
||||||
|
note 2: some algorithms feature _faster than RAM_ speed. In which case, they can only reach their full speed potential when input is already in CPU cache (L3 or better). Otherwise, they max out on RAM speed limit.
|
||||||
|
|
||||||
|
### Small data
|
||||||
|
|
||||||
|
Performance on large data is only one part of the picture.
|
||||||
|
Hashing is also very useful in constructions like hash tables and bloom filters.
|
||||||
|
In these use cases, it's frequent to hash a lot of small data (starting at a few bytes).
|
||||||
|
Algorithm's performance can be very different for such scenarios, since parts of the algorithm,
|
||||||
|
such as initialization or finalization, become fixed cost.
|
||||||
|
The impact of branch mis-prediction also becomes much more present.
|
||||||
|
|
||||||
|
XXH3 has been designed for excellent performance on both long and small inputs,
|
||||||
|
which can be observed in the following graph:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
For a more detailed analysis, please visit the wiki :
|
||||||
|
https://github.com/Cyan4973/xxHash/wiki/Performance-comparison#benchmarks-concentrating-on-small-data-
|
||||||
|
|
||||||
|
Quality
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Speed is not the only property that matters.
|
||||||
|
Produced hash values must respect excellent dispersion and randomness properties,
|
||||||
|
so that any sub-section of it can be used to maximally spread out a table or index,
|
||||||
|
as well as reduce the amount of collisions to the minimal theoretical level, following the [birthday paradox].
|
||||||
|
|
||||||
|
`xxHash` has been tested with Austin Appleby's excellent SMHasher test suite,
|
||||||
|
and passes all tests, ensuring reasonable quality levels.
|
||||||
|
It also passes extended tests from [newer forks of SMHasher], featuring additional scenarios and conditions.
|
||||||
|
|
||||||
|
Finally, xxHash provides its own [massive collision tester](https://github.com/Cyan4973/xxHash/tree/dev/tests/collisions),
|
||||||
|
able to generate and compare billions of hashes to test the limits of 64-bit hash algorithms.
|
||||||
|
On this front too, xxHash features good results, in line with the [birthday paradox].
|
||||||
|
A more detailed analysis is documented [in the wiki](https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison).
|
||||||
|
|
||||||
|
[birthday paradox]: https://en.wikipedia.org/wiki/Birthday_problem
|
||||||
|
[newer forks of SMHasher]: https://github.com/rurban/smhasher
|
||||||
|
|
||||||
|
|
||||||
|
### Build modifiers
|
||||||
|
|
||||||
|
The following macros can be set at compilation time to modify `libxxhash`'s behavior. They are generally disabled by default.
|
||||||
|
|
||||||
|
- `XXH_INLINE_ALL`: Make all functions `inline`, implementation is directly included within `xxhash.h`.
|
||||||
|
Inlining functions is beneficial for speed, notably for small keys.
|
||||||
|
It's _extremely effective_ when key's length is expressed as _a compile time constant_,
|
||||||
|
with performance improvements observed in the +200% range .
|
||||||
|
See [this article](https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html) for details.
|
||||||
|
- `XXH_PRIVATE_API`: same outcome as `XXH_INLINE_ALL`. Still available for legacy support.
|
||||||
|
The name underlines that `XXH_*` symbol names will not be exported.
|
||||||
|
- `XXH_STATIC_LINKING_ONLY`: gives access to internal state declaration, required for static allocation.
|
||||||
|
Incompatible with dynamic linking, due to risks of ABI changes.
|
||||||
|
- `XXH_NAMESPACE`: Prefixes all symbols with the value of `XXH_NAMESPACE`.
|
||||||
|
This macro can only use compilable character set.
|
||||||
|
Useful to evade symbol naming collisions,
|
||||||
|
in case of multiple inclusions of xxHash's source code.
|
||||||
|
Client applications still use the regular function names,
|
||||||
|
as symbols are automatically translated through `xxhash.h`.
|
||||||
|
- `XXH_FORCE_ALIGN_CHECK`: Use a faster direct read path when input is aligned.
|
||||||
|
This option can result in dramatic performance improvement on architectures unable to load memory from unaligned addresses
|
||||||
|
when input to hash happens to be aligned on 32 or 64-bit boundaries.
|
||||||
|
It is (slightly) detrimental on platform with good unaligned memory access performance (same instruction for both aligned and unaligned accesses).
|
||||||
|
This option is automatically disabled on `x86`, `x64` and `aarch64`, and enabled on all other platforms.
|
||||||
|
- `XXH_FORCE_MEMORY_ACCESS`: The default method `0` uses a portable `memcpy()` notation.
|
||||||
|
Method `1` uses a gcc-specific `packed` attribute, which can provide better performance for some targets.
|
||||||
|
Method `2` forces unaligned reads, which is not standard compliant, but might sometimes be the only way to extract better read performance.
|
||||||
|
Method `3` uses a byteshift operation, which is best for old compilers which don't inline `memcpy()` or big-endian systems without a byteswap instruction.
|
||||||
|
- `XXH_CPU_LITTLE_ENDIAN`: By default, endianness is determined by a runtime test resolved at compile time.
|
||||||
|
If, for some reason, the compiler cannot simplify the runtime test, it can cost performance.
|
||||||
|
It's possible to skip auto-detection and simply state that the architecture is little-endian by setting this macro to 1.
|
||||||
|
Setting it to 0 states big-endian.
|
||||||
|
- `XXH_ENABLE_AUTOVECTORIZE`: Auto-vectorization may be triggered for XXH32 and XXH64, depending on cpu vector capabilities and compiler version.
|
||||||
|
Note: auto-vectorization tends to be triggered more easily with recent versions of `clang`.
|
||||||
|
For XXH32, SSE4.1 or equivalent (NEON) is enough, while XXH64 requires AVX512.
|
||||||
|
Unfortunately, auto-vectorization is generally detrimental to XXH performance.
|
||||||
|
For this reason, the xxhash source code tries to prevent auto-vectorization by default.
|
||||||
|
That being said, systems evolve, and this conclusion is not forthcoming.
|
||||||
|
For example, it has been reported that recent Zen4 cpus are more likely to improve performance with vectorization.
|
||||||
|
Therefore, should you prefer or want to test vectorized code, you can enable this flag:
|
||||||
|
it will remove the no-vectorization protection code, thus making it more likely for XXH32 and XXH64 to be auto-vectorized.
|
||||||
|
- `XXH32_ENDJMP`: Switch multi-branch finalization stage of XXH32 by a single jump.
|
||||||
|
This is generally undesirable for performance, especially when hashing inputs of random sizes.
|
||||||
|
But depending on exact architecture and compiler, a jump might provide slightly better performance on small inputs. Disabled by default.
|
||||||
|
- `XXH_IMPORT`: MSVC specific: should only be defined for dynamic linking, as it prevents linkage errors.
|
||||||
|
- `XXH_NO_STDLIB`: Disable invocation of `<stdlib.h>` functions, notably `malloc()` and `free()`.
|
||||||
|
`libxxhash`'s `XXH*_createState()` will always fail and return `NULL`.
|
||||||
|
But one-shot hashing (like `XXH32()`) or streaming using statically allocated states
|
||||||
|
still work as expected.
|
||||||
|
This build flag is useful for embedded environments without dynamic allocation.
|
||||||
|
- `XXH_memcpy`, `XXH_memset`, `XXH_memcmp` : redirect `memcpy()`, `memset()` and `memcmp()` to some user-selected symbol at compile time.
|
||||||
|
Redirecting all 3 removes the need to include `<string.h>` standard library.
|
||||||
|
- `XXH_NO_EXTERNC_GUARD`: When `xxhash.h` is compiled in C++ mode, removes the `extern "C" { .. }` block guard.
|
||||||
|
- `XXH_DEBUGLEVEL` : When set to any value >= 1, enables `assert()` statements.
|
||||||
|
This (slightly) slows down execution, but may help finding bugs during debugging sessions.
|
||||||
|
|
||||||
|
#### Binary size control
|
||||||
|
- `XXH_NO_XXH3` : removes symbols related to `XXH3` (both 64 & 128 bits) from generated binary.
|
||||||
|
`XXH3` is by far the largest contributor to `libxxhash` size,
|
||||||
|
so it's useful to reduce binary size for applications which do not employ `XXH3`.
|
||||||
|
- `XXH_NO_LONG_LONG`: removes compilation of algorithms relying on 64-bit `long long` types
|
||||||
|
which include `XXH3` and `XXH64`.
|
||||||
|
Only `XXH32` will be compiled.
|
||||||
|
Useful for targets (architectures and compilers) without 64-bit support.
|
||||||
|
- `XXH_NO_STREAM`: Disables the streaming API, limiting the library to single shot variants only.
|
||||||
|
- `XXH_NO_INLINE_HINTS`: By default, xxHash uses `__attribute__((always_inline))` and `__forceinline` to improve performance at the cost of code size.
|
||||||
|
Defining this macro to 1 will mark all internal functions as `static`, allowing the compiler to decide whether to inline a function or not.
|
||||||
|
This is very useful when optimizing for smallest binary size,
|
||||||
|
and is automatically defined when compiling with `-O0`, `-Os`, `-Oz`, or `-fno-inline` on GCC and Clang.
|
||||||
|
It may also be required to successfully compile using `-Og`, depending on compiler version.
|
||||||
|
- `XXH_SIZE_OPT`: `0`: default, optimize for speed
|
||||||
|
`1`: default for `-Os` and `-Oz`: disables some speed hacks for size optimization
|
||||||
|
`2`: makes code as small as possible, performance may cry
|
||||||
|
|
||||||
|
#### Build modifiers specific for XXH3
|
||||||
|
- `XXH_VECTOR` : manually select a vector instruction set (default: auto-selected at compilation time). Available instruction sets are `XXH_SCALAR`, `XXH_SSE2`, `XXH_AVX2`, `XXH_AVX512`, `XXH_NEON` and `XXH_VSX`. Compiler may require additional flags to ensure proper support (for example, `gcc` on x86_64 requires `-mavx2` for `AVX2`, or `-mavx512f` for `AVX512`).
|
||||||
|
- `XXH_PREFETCH_DIST` : select prefetching distance. For close-to-metal adaptation to specific hardware platforms. XXH3 only.
|
||||||
|
- `XXH_NO_PREFETCH` : disable prefetching. Some platforms or situations may perform better without prefetching. XXH3 only.
|
||||||
|
|
||||||
|
#### Makefile variables
|
||||||
|
When compiling the Command Line Interface `xxhsum` using `make`, the following environment variables can also be set :
|
||||||
|
- `DISPATCH=1` : use `xxh_x86dispatch.c`, select at runtime between `scalar`, `sse2`, `avx2` or `avx512` instruction set. This option is only valid for `x86`/`x64` systems. It is enabled by default when target `x86`/`x64` is detected. It can be forcefully turned off using `DISPATCH=0`.
|
||||||
|
- `LIBXXH_DISPATCH=1` : same idea, implemented a runtime vector extension detector, but within `libxxhash`. This parameter is disabled by default. When enabled (only valid for `x86`/`x64` systems), new symbols published in `xxh_x86dispatch.h` become accessible. At the time of this writing, it's required to include `xxh_x86dispatch.h` in order to access the symbols with runtime vector extension detection.
|
||||||
|
- `XXH_1ST_SPEED_TARGET` : select an initial speed target, expressed in MB/s, for the first speed test in benchmark mode. Benchmark will adjust the target at subsequent iterations, but the first test is made "blindly" by targeting this speed. Currently conservatively set to 10 MB/s, to support very slow (emulated) platforms.
|
||||||
|
- `NODE_JS=1` : When compiling `xxhsum` for Node.js with Emscripten, this links the `NODERAWFS` library for unrestricted filesystem access and patches `isatty` to make the command line utility correctly detect the terminal. This does make the binary specific to Node.js.
|
||||||
|
|
||||||
|
### Building xxHash - Using vcpkg
|
||||||
|
|
||||||
|
You can download and install xxHash using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||||
|
|
||||||
|
git clone https://github.com/Microsoft/vcpkg.git
|
||||||
|
cd vcpkg
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
./vcpkg integrate install
|
||||||
|
./vcpkg install xxhash
|
||||||
|
|
||||||
|
The xxHash port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The simplest example calls xxhash 64-bit variant as a one-shot function
|
||||||
|
generating a hash value from a single buffer, and invoked from a C/C++ program:
|
||||||
|
|
||||||
|
```C
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
|
(...)
|
||||||
|
XXH64_hash_t hash = XXH64(buffer, size, seed);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Streaming variant is more involved, but makes it possible to provide data incrementally:
|
||||||
|
|
||||||
|
```C
|
||||||
|
#include "stdlib.h" /* abort() */
|
||||||
|
#include "xxhash.h"
|
||||||
|
|
||||||
|
|
||||||
|
XXH64_hash_t calcul_hash_streaming(FileHandler fh)
|
||||||
|
{
|
||||||
|
/* create a hash state */
|
||||||
|
XXH64_state_t* const state = XXH64_createState();
|
||||||
|
if (state==NULL) abort();
|
||||||
|
|
||||||
|
size_t const bufferSize = SOME_SIZE;
|
||||||
|
void* const buffer = malloc(bufferSize);
|
||||||
|
if (buffer==NULL) abort();
|
||||||
|
|
||||||
|
/* Initialize state with selected seed */
|
||||||
|
XXH64_hash_t const seed = 0; /* or any other value */
|
||||||
|
if (XXH64_reset(state, seed) == XXH_ERROR) abort();
|
||||||
|
|
||||||
|
/* Feed the state with input data, any size, any number of times */
|
||||||
|
(...)
|
||||||
|
while ( /* some data left */ ) {
|
||||||
|
size_t const length = get_more_data(buffer, bufferSize, fh);
|
||||||
|
if (XXH64_update(state, buffer, length) == XXH_ERROR) abort();
|
||||||
|
(...)
|
||||||
|
}
|
||||||
|
(...)
|
||||||
|
|
||||||
|
/* Produce the final hash value */
|
||||||
|
XXH64_hash_t const hash = XXH64_digest(state);
|
||||||
|
|
||||||
|
/* State could be re-used; but in this example, it is simply freed */
|
||||||
|
free(buffer);
|
||||||
|
XXH64_freeState(state);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
The library files `xxhash.c` and `xxhash.h` are BSD licensed.
|
||||||
|
The utility `xxhsum` is GPL licensed.
|
||||||
|
|
||||||
|
|
||||||
|
### Other programming languages
|
||||||
|
|
||||||
|
Beyond the C reference version,
|
||||||
|
xxHash is also available from many different programming languages,
|
||||||
|
thanks to great contributors.
|
||||||
|
They are [listed here](http://www.xxhash.com/#other-languages).
|
||||||
|
|
||||||
|
|
||||||
|
### Packaging status
|
||||||
|
|
||||||
|
Many distributions bundle a package manager
|
||||||
|
which allows easy xxhash installation as both a `libxxhash` library
|
||||||
|
and `xxhsum` command line interface.
|
||||||
|
|
||||||
|
[](https://repology.org/project/xxhash/versions)
|
||||||
|
|
||||||
|
|
||||||
|
### Special Thanks
|
||||||
|
|
||||||
|
- Takayuki Matsuoka, aka @t-mat, for creating `xxhsum -c` and great support during early xxh releases
|
||||||
|
- Mathias Westerdahl, aka @JCash, for introducing the first version of `XXH64`
|
||||||
|
- Devin Hussey, aka @easyaspi314, for incredible low-level optimizations on `XXH3` and `XXH128`
|
||||||
13
external/xxhash/SECURITY.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Security updates are applied only to the latest release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||||
|
|
||||||
|
Please disclose it at [security advisory](https://github.com/Cyan4973/xxHash/security/advisories/new).
|
||||||
|
|
||||||
|
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
|
||||||
55
external/xxhash/xxh3.h
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* xxHash - Extremely Fast Hash algorithm
|
||||||
|
* Development source file for `xxh3`
|
||||||
|
* Copyright (C) 2019-2021 Yann Collet
|
||||||
|
*
|
||||||
|
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - xxHash homepage: https://www.xxhash.com
|
||||||
|
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: This file used to host the source code of XXH3_* variants.
|
||||||
|
* during the development period.
|
||||||
|
* The source code is now properly integrated within xxhash.h.
|
||||||
|
*
|
||||||
|
* xxh3.h is no longer useful,
|
||||||
|
* but it is still provided for compatibility with source code
|
||||||
|
* which used to include it directly.
|
||||||
|
*
|
||||||
|
* Programs are now highly discouraged to include xxh3.h.
|
||||||
|
* Include `xxhash.h` instead, which is the officially supported interface.
|
||||||
|
*
|
||||||
|
* In the future, xxh3.h will start to generate warnings, then errors,
|
||||||
|
* then it will be removed from source package and from include directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Simulate the same impact as including the old xxh3.h source file */
|
||||||
|
|
||||||
|
#define XXH_INLINE_ALL
|
||||||
|
#include "xxhash.h"
|
||||||
821
external/xxhash/xxh_x86dispatch.c
vendored
Normal file
@ -0,0 +1,821 @@
|
|||||||
|
/*
|
||||||
|
* xxHash - Extremely Fast Hash algorithm
|
||||||
|
* Copyright (C) 2020-2021 Yann Collet
|
||||||
|
*
|
||||||
|
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - xxHash homepage: https://www.xxhash.com
|
||||||
|
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file xxh_x86dispatch.c
|
||||||
|
*
|
||||||
|
* Automatic dispatcher code for the @ref XXH3_family on x86-based targets.
|
||||||
|
*
|
||||||
|
* Optional add-on.
|
||||||
|
*
|
||||||
|
* **Compile this file with the default flags for your target.**
|
||||||
|
* Note that compiling with flags like `-mavx*`, `-march=native`, or `/arch:AVX*`
|
||||||
|
* will make the resulting binary incompatible with cpus not supporting the requested instruction set.
|
||||||
|
*
|
||||||
|
* @defgroup dispatch x86 Dispatcher
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64))
|
||||||
|
# error "Dispatching is currently only supported on x86 and x86_64."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#ifndef XXH_HAS_INCLUDE
|
||||||
|
# ifdef __has_include
|
||||||
|
/*
|
||||||
|
* Not defined as XXH_HAS_INCLUDE(x) (function-like) because
|
||||||
|
* this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion)
|
||||||
|
*/
|
||||||
|
# define XXH_HAS_INCLUDE __has_include
|
||||||
|
# else
|
||||||
|
# define XXH_HAS_INCLUDE(x) 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @def XXH_DISPATCH_SCALAR
|
||||||
|
* @brief Enables/dispatching the scalar code path.
|
||||||
|
*
|
||||||
|
* If this is defined to 0, SSE2 support is assumed. This reduces code size
|
||||||
|
* when the scalar path is not needed.
|
||||||
|
*
|
||||||
|
* This is automatically defined to 0 when...
|
||||||
|
* - SSE2 support is enabled in the compiler
|
||||||
|
* - Targeting x86_64
|
||||||
|
* - Targeting Android x86
|
||||||
|
* - Targeting macOS
|
||||||
|
*/
|
||||||
|
#ifndef XXH_DISPATCH_SCALAR
|
||||||
|
# if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \
|
||||||
|
|| defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \
|
||||||
|
|| defined(__ANDROID__) || defined(__APPLE__) /* Android or macOS */
|
||||||
|
# define XXH_DISPATCH_SCALAR 0 /* disable */
|
||||||
|
# else
|
||||||
|
# define XXH_DISPATCH_SCALAR 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
/*!
|
||||||
|
* @def XXH_DISPATCH_AVX2
|
||||||
|
* @brief Enables/disables dispatching for AVX2.
|
||||||
|
*
|
||||||
|
* This is automatically detected if it is not defined.
|
||||||
|
* - GCC 4.7 and later are known to support AVX2, but >4.9 is required for
|
||||||
|
* to get the AVX2 intrinsics and typedefs without -mavx -mavx2.
|
||||||
|
* - Visual Studio 2013 Update 2 and later are known to support AVX2.
|
||||||
|
* - The GCC/Clang internal header `<avx2intrin.h>` is detected. While this is
|
||||||
|
* not allowed to be included directly, it still appears in the builtin
|
||||||
|
* include path and is detectable with `__has_include`.
|
||||||
|
*
|
||||||
|
* @see XXH_AVX2
|
||||||
|
*/
|
||||||
|
#ifndef XXH_DISPATCH_AVX2
|
||||||
|
# if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \
|
||||||
|
|| (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \
|
||||||
|
|| (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \
|
||||||
|
|| XXH_HAS_INCLUDE(<avx2intrin.h>) /* GCC/Clang internal header */
|
||||||
|
# define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */
|
||||||
|
# else
|
||||||
|
# define XXH_DISPATCH_AVX2 0
|
||||||
|
# endif
|
||||||
|
#endif /* XXH_DISPATCH_AVX2 */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @def XXH_DISPATCH_AVX512
|
||||||
|
* @brief Enables/disables dispatching for AVX512.
|
||||||
|
*
|
||||||
|
* Automatically detected if one of the following conditions is met:
|
||||||
|
* - GCC 4.9 and later are known to support AVX512.
|
||||||
|
* - Visual Studio 2017 and later are known to support AVX2.
|
||||||
|
* - The GCC/Clang internal header `<avx512fintrin.h>` is detected. While this
|
||||||
|
* is not allowed to be included directly, it still appears in the builtin
|
||||||
|
* include path and is detectable with `__has_include`.
|
||||||
|
*
|
||||||
|
* @see XXH_AVX512
|
||||||
|
*/
|
||||||
|
#ifndef XXH_DISPATCH_AVX512
|
||||||
|
# if (defined(__GNUC__) \
|
||||||
|
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \
|
||||||
|
|| (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \
|
||||||
|
|| XXH_HAS_INCLUDE(<avx512fintrin.h>) /* GCC/Clang internal header */
|
||||||
|
# define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */
|
||||||
|
# else
|
||||||
|
# define XXH_DISPATCH_AVX512 0
|
||||||
|
# endif
|
||||||
|
#endif /* XXH_DISPATCH_AVX512 */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @def XXH_TARGET_SSE2
|
||||||
|
* @brief Allows a function to be compiled with SSE2 intrinsics.
|
||||||
|
*
|
||||||
|
* Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used
|
||||||
|
* even with `-mno-sse2`.
|
||||||
|
*
|
||||||
|
* @def XXH_TARGET_AVX2
|
||||||
|
* @brief Like @ref XXH_TARGET_SSE2, but for AVX2.
|
||||||
|
*
|
||||||
|
* @def XXH_TARGET_AVX512
|
||||||
|
* @brief Like @ref XXH_TARGET_SSE2, but for AVX512.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# include <emmintrin.h> /* SSE2 */
|
||||||
|
# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512
|
||||||
|
# include <immintrin.h> /* AVX2, AVX512F */
|
||||||
|
# endif
|
||||||
|
# define XXH_TARGET_SSE2 __attribute__((__target__("sse2")))
|
||||||
|
# define XXH_TARGET_AVX2 __attribute__((__target__("avx2")))
|
||||||
|
# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f")))
|
||||||
|
#elif defined(__clang__) && defined(_MSC_VER) /* clang-cl.exe */
|
||||||
|
# include <emmintrin.h> /* SSE2 */
|
||||||
|
# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512
|
||||||
|
# include <immintrin.h> /* AVX2, AVX512F */
|
||||||
|
# include <smmintrin.h>
|
||||||
|
# include <avxintrin.h>
|
||||||
|
# include <avx2intrin.h>
|
||||||
|
# include <avx512fintrin.h>
|
||||||
|
# endif
|
||||||
|
# define XXH_TARGET_SSE2 __attribute__((__target__("sse2")))
|
||||||
|
# define XXH_TARGET_AVX2 __attribute__((__target__("avx2")))
|
||||||
|
# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f")))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# include <intrin.h>
|
||||||
|
# define XXH_TARGET_SSE2
|
||||||
|
# define XXH_TARGET_AVX2
|
||||||
|
# define XXH_TARGET_AVX512
|
||||||
|
#else
|
||||||
|
# error "Dispatching is currently not supported for your compiler."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#ifdef XXH_DISPATCH_DEBUG
|
||||||
|
/* debug logging */
|
||||||
|
# include <stdio.h>
|
||||||
|
# define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); }
|
||||||
|
#else
|
||||||
|
# define XXH_debugPrint(str) ((void)0)
|
||||||
|
# undef NDEBUG /* avoid redefinition */
|
||||||
|
# define NDEBUG
|
||||||
|
#endif
|
||||||
|
/*! @endcond */
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef XXH_DOXYGEN
|
||||||
|
#define XXH_INLINE_ALL
|
||||||
|
#define XXH_X86DISPATCH
|
||||||
|
#include "xxhash.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#ifndef XXH_HAS_ATTRIBUTE
|
||||||
|
# ifdef __has_attribute
|
||||||
|
# define XXH_HAS_ATTRIBUTE(...) __has_attribute(__VA_ARGS__)
|
||||||
|
# else
|
||||||
|
# define XXH_HAS_ATTRIBUTE(...) 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#if XXH_HAS_ATTRIBUTE(constructor)
|
||||||
|
# define XXH_CONSTRUCTOR __attribute__((constructor))
|
||||||
|
# define XXH_DISPATCH_MAYBE_NULL 0
|
||||||
|
#else
|
||||||
|
# define XXH_CONSTRUCTOR
|
||||||
|
# define XXH_DISPATCH_MAYBE_NULL 1
|
||||||
|
#endif
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
/*
|
||||||
|
* Support both AT&T and Intel dialects
|
||||||
|
*
|
||||||
|
* GCC doesn't convert AT&T syntax to Intel syntax, and will error out if
|
||||||
|
* compiled with -masm=intel. Instead, it supports dialect switching with
|
||||||
|
* curly braces: { AT&T syntax | Intel syntax }
|
||||||
|
*
|
||||||
|
* Clang's integrated assembler automatically converts AT&T syntax to Intel if
|
||||||
|
* needed, making the dialect switching useless (it isn't even supported).
|
||||||
|
*
|
||||||
|
* Note: Comments are written in the inline assembly itself.
|
||||||
|
*/
|
||||||
|
#ifdef __clang__
|
||||||
|
# define XXH_I_ATT(intel, att) att "\n\t"
|
||||||
|
#else
|
||||||
|
# define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t"
|
||||||
|
#endif
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Runs CPUID.
|
||||||
|
*
|
||||||
|
* @param eax , ecx The parameters to pass to CPUID, %eax and %ecx respectively.
|
||||||
|
* @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }`
|
||||||
|
*/
|
||||||
|
static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
__cpuidex((int*)abcd, eax, ecx);
|
||||||
|
#else
|
||||||
|
xxh_u32 ebx, edx;
|
||||||
|
# if defined(__i386__) && defined(__PIC__)
|
||||||
|
__asm__(
|
||||||
|
"# Call CPUID\n\t"
|
||||||
|
"#\n\t"
|
||||||
|
"# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t"
|
||||||
|
"# EBX, so we use EDI instead.\n\t"
|
||||||
|
XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi")
|
||||||
|
XXH_I_ATT("cpuid", "cpuid" )
|
||||||
|
XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi")
|
||||||
|
: "=D" (ebx),
|
||||||
|
# else
|
||||||
|
__asm__(
|
||||||
|
"# Call CPUID\n\t"
|
||||||
|
XXH_I_ATT("cpuid", "cpuid")
|
||||||
|
: "=b" (ebx),
|
||||||
|
# endif
|
||||||
|
"+a" (eax), "+c" (ecx), "=d" (edx));
|
||||||
|
abcd[0] = eax;
|
||||||
|
abcd[1] = ebx;
|
||||||
|
abcd[2] = ecx;
|
||||||
|
abcd[3] = edx;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified version of Intel's guide
|
||||||
|
* https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Runs `XGETBV`.
|
||||||
|
*
|
||||||
|
* While the CPU may support AVX2, the operating system might not properly save
|
||||||
|
* the full YMM/ZMM registers.
|
||||||
|
*
|
||||||
|
* xgetbv is used for detecting this: Any compliant operating system will define
|
||||||
|
* a set of flags in the xcr0 register indicating how it saves the AVX registers.
|
||||||
|
*
|
||||||
|
* You can manually disable this flag on Windows by running, as admin:
|
||||||
|
*
|
||||||
|
* bcdedit.exe /set xsavedisable 1
|
||||||
|
*
|
||||||
|
* and rebooting. Run the same command with 0 to re-enable it.
|
||||||
|
*/
|
||||||
|
static xxh_u64 XXH_xgetbv(void)
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
return _xgetbv(0); /* min VS2010 SP1 compiler is required */
|
||||||
|
#else
|
||||||
|
xxh_u32 xcr0_lo, xcr0_hi;
|
||||||
|
__asm__(
|
||||||
|
"# Call XGETBV\n\t"
|
||||||
|
"#\n\t"
|
||||||
|
"# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t"
|
||||||
|
"# the XGETBV opcode, so we encode it by hand instead.\n\t"
|
||||||
|
"# See <https://github.com/asmjit/asmjit/issues/78> for details.\n\t"
|
||||||
|
".byte 0x0f, 0x01, 0xd0\n\t"
|
||||||
|
: "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0));
|
||||||
|
return xcr0_lo | ((xxh_u64)xcr0_hi << 32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#define XXH_SSE2_CPUID_MASK (1 << 26)
|
||||||
|
#define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27))
|
||||||
|
#define XXH_AVX2_CPUID_MASK (1 << 5)
|
||||||
|
#define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1))
|
||||||
|
#define XXH_AVX512F_CPUID_MASK (1 << 16)
|
||||||
|
#define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1))
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Returns the best XXH3 implementation.
|
||||||
|
*
|
||||||
|
* Runs various CPUID/XGETBV tests to try and determine the best implementation.
|
||||||
|
*
|
||||||
|
* @return The best @ref XXH_VECTOR implementation.
|
||||||
|
* @see XXH_VECTOR_TYPES
|
||||||
|
*/
|
||||||
|
int XXH_featureTest(void)
|
||||||
|
{
|
||||||
|
xxh_u32 abcd[4];
|
||||||
|
xxh_u32 max_leaves;
|
||||||
|
int best = XXH_SCALAR;
|
||||||
|
#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512
|
||||||
|
xxh_u64 xgetbv_val;
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) && defined(__i386__)
|
||||||
|
xxh_u32 cpuid_supported;
|
||||||
|
__asm__(
|
||||||
|
"# For the sake of ruthless backwards compatibility, check if CPUID\n\t"
|
||||||
|
"# is supported in the EFLAGS on i386.\n\t"
|
||||||
|
"# This is not necessary on x86_64 - CPUID is mandatory.\n\t"
|
||||||
|
"# The ID flag (bit 21) in the EFLAGS register indicates support\n\t"
|
||||||
|
"# for the CPUID instruction. If a software procedure can set and\n\t"
|
||||||
|
"# clear this flag, the processor executing the procedure supports\n\t"
|
||||||
|
"# the CPUID instruction.\n\t"
|
||||||
|
"# <https://c9x.me/x86/html/file_module_x86_id_45.html>\n\t"
|
||||||
|
"#\n\t"
|
||||||
|
"# Routine is from <https://wiki.osdev.org/CPUID>.\n\t"
|
||||||
|
|
||||||
|
"# Save EFLAGS\n\t"
|
||||||
|
XXH_I_ATT("pushfd", "pushfl" )
|
||||||
|
"# Store EFLAGS\n\t"
|
||||||
|
XXH_I_ATT("pushfd", "pushfl" )
|
||||||
|
"# Invert the ID bit in stored EFLAGS\n\t"
|
||||||
|
XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)")
|
||||||
|
"# Load stored EFLAGS (with ID bit inverted)\n\t"
|
||||||
|
XXH_I_ATT("popfd", "popfl" )
|
||||||
|
"# Store EFLAGS again (ID bit may or not be inverted)\n\t"
|
||||||
|
XXH_I_ATT("pushfd", "pushfl" )
|
||||||
|
"# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t"
|
||||||
|
XXH_I_ATT("pop eax", "popl %%eax" )
|
||||||
|
"# eax = whichever bits were changed\n\t"
|
||||||
|
XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" )
|
||||||
|
"# Restore original EFLAGS\n\t"
|
||||||
|
XXH_I_ATT("popfd", "popfl" )
|
||||||
|
"# eax = zero if ID bit can't be changed, else non-zero\n\t"
|
||||||
|
XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" )
|
||||||
|
: "=a" (cpuid_supported) :: "cc");
|
||||||
|
|
||||||
|
if (XXH_unlikely(!cpuid_supported)) {
|
||||||
|
XXH_debugPrint("CPUID support is not detected!");
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* Check how many CPUID pages we have */
|
||||||
|
XXH_cpuid(0, 0, abcd);
|
||||||
|
max_leaves = abcd[0];
|
||||||
|
|
||||||
|
/* Shouldn't happen on hardware, but happens on some QEMU configs. */
|
||||||
|
if (XXH_unlikely(max_leaves == 0)) {
|
||||||
|
XXH_debugPrint("Max CPUID leaves == 0!");
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for SSE2, OSXSAVE and xgetbv */
|
||||||
|
XXH_cpuid(1, 0, abcd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test for SSE2. The check is redundant on x86_64, but it doesn't hurt.
|
||||||
|
*/
|
||||||
|
if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK))
|
||||||
|
return best;
|
||||||
|
|
||||||
|
XXH_debugPrint("SSE2 support detected.");
|
||||||
|
|
||||||
|
best = XXH_SSE2;
|
||||||
|
#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512
|
||||||
|
/* Make sure we have enough leaves */
|
||||||
|
if (XXH_unlikely(max_leaves < 7))
|
||||||
|
return best;
|
||||||
|
|
||||||
|
/* Test for OSXSAVE and XGETBV */
|
||||||
|
if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK)
|
||||||
|
return best;
|
||||||
|
|
||||||
|
/* CPUID check for AVX features */
|
||||||
|
XXH_cpuid(7, 0, abcd);
|
||||||
|
|
||||||
|
xgetbv_val = XXH_xgetbv();
|
||||||
|
#if XXH_DISPATCH_AVX2
|
||||||
|
/* Validate that AVX2 is supported by the CPU */
|
||||||
|
if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK)
|
||||||
|
return best;
|
||||||
|
|
||||||
|
/* Validate that the OS supports YMM registers */
|
||||||
|
if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) {
|
||||||
|
XXH_debugPrint("AVX2 supported by the CPU, but not the OS.");
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AVX2 supported */
|
||||||
|
XXH_debugPrint("AVX2 support detected.");
|
||||||
|
best = XXH_AVX2;
|
||||||
|
#endif
|
||||||
|
#if XXH_DISPATCH_AVX512
|
||||||
|
/* Check if AVX512F is supported by the CPU */
|
||||||
|
if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) {
|
||||||
|
XXH_debugPrint("AVX512F not supported by CPU");
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate that the OS supports ZMM registers */
|
||||||
|
if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) {
|
||||||
|
XXH_debugPrint("AVX512F supported by the CPU, but not the OS.");
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AVX512F supported */
|
||||||
|
XXH_debugPrint("AVX512F support detected.");
|
||||||
|
best = XXH_AVX512;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* === Vector implementations === */
|
||||||
|
|
||||||
|
/*! @cond PRIVATE */
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Defines the various dispatch functions.
|
||||||
|
*
|
||||||
|
* TODO: Consolidate?
|
||||||
|
*
|
||||||
|
* @param suffix The suffix for the functions, e.g. sse2 or scalar
|
||||||
|
* @param target XXH_TARGET_* or empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \
|
||||||
|
\
|
||||||
|
/* === XXH3, default variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH64_hash_t \
|
||||||
|
XXHL64_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \
|
||||||
|
size_t len) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_64b_internal( \
|
||||||
|
input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH3, Seeded variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH64_hash_t \
|
||||||
|
XXHL64_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len, \
|
||||||
|
XXH64_hash_t seed) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_64b_withSeed_internal( \
|
||||||
|
input, len, seed, XXH3_accumulate_##suffix, \
|
||||||
|
XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH3, Secret variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH64_hash_t \
|
||||||
|
XXHL64_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \
|
||||||
|
size_t len, XXH_NOESCAPE const void* secret, \
|
||||||
|
size_t secretLen) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_64b_internal( \
|
||||||
|
input, len, secret, secretLen, \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH3 update variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH_errorcode \
|
||||||
|
XXH3_update_##suffix(XXH_NOESCAPE XXH3_state_t* state, \
|
||||||
|
XXH_NOESCAPE const void* input, size_t len) \
|
||||||
|
{ \
|
||||||
|
return XXH3_update(state, (const xxh_u8*)input, len, \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH128 default variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH128_hash_t \
|
||||||
|
XXHL128_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \
|
||||||
|
size_t len) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_128b_internal( \
|
||||||
|
input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH128 Secret variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH128_hash_t \
|
||||||
|
XXHL128_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \
|
||||||
|
size_t len, \
|
||||||
|
XXH_NOESCAPE const void* XXH_RESTRICT secret, \
|
||||||
|
size_t secretLen) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_128b_internal( \
|
||||||
|
input, len, (const xxh_u8*)secret, secretLen, \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* === XXH128 Seeded variants === */ \
|
||||||
|
\
|
||||||
|
XXH_NO_INLINE target XXH128_hash_t \
|
||||||
|
XXHL128_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len,\
|
||||||
|
XXH64_hash_t seed) \
|
||||||
|
{ \
|
||||||
|
return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \
|
||||||
|
XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix, \
|
||||||
|
XXH3_initCustomSecret_##suffix); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @endcond */
|
||||||
|
/* End XXH_DEFINE_DISPATCH_FUNCS */
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
#if XXH_DISPATCH_SCALAR
|
||||||
|
XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */)
|
||||||
|
#endif
|
||||||
|
XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2)
|
||||||
|
#if XXH_DISPATCH_AVX2
|
||||||
|
XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2)
|
||||||
|
#endif
|
||||||
|
#if XXH_DISPATCH_AVX512
|
||||||
|
XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512)
|
||||||
|
#endif
|
||||||
|
#undef XXH_DEFINE_DISPATCH_FUNCS
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/* ==== Dispatchers ==== */
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t);
|
||||||
|
|
||||||
|
typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t);
|
||||||
|
|
||||||
|
typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t);
|
||||||
|
|
||||||
|
typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH_NOESCAPE XXH3_state_t*, XXH_NOESCAPE const void*, size_t);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
XXH3_dispatchx86_hashLong64_default hashLong64_default;
|
||||||
|
XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed;
|
||||||
|
XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret;
|
||||||
|
XXH3_dispatchx86_update update;
|
||||||
|
} XXH_dispatchFunctions_s;
|
||||||
|
|
||||||
|
#define XXH_NB_DISPATCHES 4
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Table of dispatchers for @ref XXH3_64bits().
|
||||||
|
*
|
||||||
|
* @pre The indices must match @ref XXH_VECTOR_TYPE.
|
||||||
|
*/
|
||||||
|
static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = {
|
||||||
|
#if XXH_DISPATCH_SCALAR
|
||||||
|
/* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar },
|
||||||
|
#else
|
||||||
|
/* Scalar */ { NULL, NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
/* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 },
|
||||||
|
#if XXH_DISPATCH_AVX2
|
||||||
|
/* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 },
|
||||||
|
#else
|
||||||
|
/* AVX2 */ { NULL, NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
#if XXH_DISPATCH_AVX512
|
||||||
|
/* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 }
|
||||||
|
#else
|
||||||
|
/* AVX512 */ { NULL, NULL, NULL, NULL }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief The selected dispatch table for @ref XXH3_64bits().
|
||||||
|
*/
|
||||||
|
static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL };
|
||||||
|
|
||||||
|
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t);
|
||||||
|
|
||||||
|
typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t);
|
||||||
|
|
||||||
|
typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
XXH3_dispatchx86_hashLong128_default hashLong128_default;
|
||||||
|
XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed;
|
||||||
|
XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret;
|
||||||
|
XXH3_dispatchx86_update update;
|
||||||
|
} XXH_dispatch128Functions_s;
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Table of dispatchers for @ref XXH3_128bits().
|
||||||
|
*
|
||||||
|
* @pre The indices must match @ref XXH_VECTOR_TYPE.
|
||||||
|
*/
|
||||||
|
static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = {
|
||||||
|
#if XXH_DISPATCH_SCALAR
|
||||||
|
/* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar },
|
||||||
|
#else
|
||||||
|
/* Scalar */ { NULL, NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
/* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 },
|
||||||
|
#if XXH_DISPATCH_AVX2
|
||||||
|
/* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 },
|
||||||
|
#else
|
||||||
|
/* AVX2 */ { NULL, NULL, NULL, NULL },
|
||||||
|
#endif
|
||||||
|
#if XXH_DISPATCH_AVX512
|
||||||
|
/* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 }
|
||||||
|
#else
|
||||||
|
/* AVX512 */ { NULL, NULL, NULL, NULL }
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief The selected dispatch table for @ref XXH3_64bits().
|
||||||
|
*/
|
||||||
|
static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL };
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @private
|
||||||
|
* @brief Runs a CPUID check and sets the correct dispatch tables.
|
||||||
|
*/
|
||||||
|
static XXH_CONSTRUCTOR void XXH_setDispatch(void)
|
||||||
|
{
|
||||||
|
int vecID = XXH_featureTest();
|
||||||
|
XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1);
|
||||||
|
assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512);
|
||||||
|
#if !XXH_DISPATCH_SCALAR
|
||||||
|
assert(vecID != XXH_SCALAR);
|
||||||
|
#endif
|
||||||
|
#if !XXH_DISPATCH_AVX512
|
||||||
|
assert(vecID != XXH_AVX512);
|
||||||
|
#endif
|
||||||
|
#if !XXH_DISPATCH_AVX2
|
||||||
|
assert(vecID != XXH_AVX2);
|
||||||
|
#endif
|
||||||
|
XXH_g_dispatch = XXH_kDispatch[vecID];
|
||||||
|
XXH_g_dispatch128 = XXH_kDispatch128[vecID];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ==== XXH3 public functions ==== */
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
|
||||||
|
static XXH64_hash_t
|
||||||
|
XXH3_hashLong_64b_defaultSecret_selection(const void* XXH_RESTRICT input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)seed64; (void)secret; (void)secretLen;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_default == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch.hashLong64_default(input, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len)
|
||||||
|
{
|
||||||
|
return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XXH64_hash_t
|
||||||
|
XXH3_hashLong_64b_withSeed_selection(const void* XXH_RESTRICT input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)secret; (void)secretLen;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_seed == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch.hashLong64_seed(input, len, seed64);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)
|
||||||
|
{
|
||||||
|
return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XXH64_hash_t
|
||||||
|
XXH3_hashLong_64b_withSecret_selection(const void* XXH_RESTRICT input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)seed64;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_secret == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH_errorcode
|
||||||
|
XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)
|
||||||
|
{
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.update == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
|
||||||
|
return XXH_g_dispatch.update(state, (const xxh_u8*)input, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
|
||||||
|
/* ==== XXH128 public functions ==== */
|
||||||
|
/*! @cond Doxygen ignores this part */
|
||||||
|
|
||||||
|
static XXH128_hash_t
|
||||||
|
XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const void* secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)seed64; (void)secret; (void)secretLen;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_default == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch128.hashLong128_default(input, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len)
|
||||||
|
{
|
||||||
|
return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XXH128_hash_t
|
||||||
|
XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const void* secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)secret; (void)secretLen;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_seed == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch128.hashLong128_seed(input, len, seed64);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)
|
||||||
|
{
|
||||||
|
return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XXH128_hash_t
|
||||||
|
XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len,
|
||||||
|
XXH64_hash_t seed64, const void* secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
(void)seed64;
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_secret == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen)
|
||||||
|
{
|
||||||
|
return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
XXH_errorcode
|
||||||
|
XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)
|
||||||
|
{
|
||||||
|
if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.update == NULL)
|
||||||
|
XXH_setDispatch();
|
||||||
|
return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @endcond */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*! @} */
|
||||||
93
external/xxhash/xxh_x86dispatch.h
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* xxHash - XXH3 Dispatcher for x86-based targets
|
||||||
|
* Copyright (C) 2020-2024 Yann Collet
|
||||||
|
*
|
||||||
|
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - xxHash homepage: https://www.xxhash.com
|
||||||
|
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XXH_X86DISPATCH_H_13563687684
|
||||||
|
#define XXH_X86DISPATCH_H_13563687684
|
||||||
|
|
||||||
|
#include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Returns the best XXH3 implementation for x86
|
||||||
|
*
|
||||||
|
* @return The best @ref XXH_VECTOR implementation.
|
||||||
|
* @see XXH_VECTOR_TYPES
|
||||||
|
*/
|
||||||
|
XXH_PUBLIC_API int XXH_featureTest(void);
|
||||||
|
|
||||||
|
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len);
|
||||||
|
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed);
|
||||||
|
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen);
|
||||||
|
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len);
|
||||||
|
|
||||||
|
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len);
|
||||||
|
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed);
|
||||||
|
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen);
|
||||||
|
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* automatic replacement of XXH3 functions.
|
||||||
|
* can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */
|
||||||
|
#ifndef XXH_DISPATCH_DISABLE_REPLACE
|
||||||
|
|
||||||
|
# undef XXH3_64bits
|
||||||
|
# define XXH3_64bits XXH3_64bits_dispatch
|
||||||
|
# undef XXH3_64bits_withSeed
|
||||||
|
# define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch
|
||||||
|
# undef XXH3_64bits_withSecret
|
||||||
|
# define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch
|
||||||
|
# undef XXH3_64bits_update
|
||||||
|
# define XXH3_64bits_update XXH3_64bits_update_dispatch
|
||||||
|
|
||||||
|
# undef XXH128
|
||||||
|
# define XXH128 XXH3_128bits_withSeed_dispatch
|
||||||
|
# undef XXH3_128bits
|
||||||
|
# define XXH3_128bits XXH3_128bits_dispatch
|
||||||
|
# undef XXH3_128bits_withSeed
|
||||||
|
# define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch
|
||||||
|
# undef XXH3_128bits_withSecret
|
||||||
|
# define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch
|
||||||
|
# undef XXH3_128bits_update
|
||||||
|
# define XXH3_128bits_update XXH3_128bits_update_dispatch
|
||||||
|
|
||||||
|
#endif /* XXH_DISPATCH_DISABLE_REPLACE */
|
||||||
|
|
||||||
|
#endif /* XXH_X86DISPATCH_H_13563687684 */
|
||||||
42
external/xxhash/xxhash.c
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* xxHash - Extremely Fast Hash algorithm
|
||||||
|
* Copyright (C) 2012-2023 Yann Collet
|
||||||
|
*
|
||||||
|
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* You can contact the author at:
|
||||||
|
* - xxHash homepage: https://www.xxhash.com
|
||||||
|
* - xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xxhash.c instantiates functions defined in xxhash.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
|
||||||
|
#define XXH_IMPLEMENTATION /* access definitions */
|
||||||
|
|
||||||
|
#include "xxhash.h"
|
||||||
7343
external/xxhash/xxhash.h
vendored
Normal file
84
src/alloc.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
static Arena *
|
||||||
|
ArenaInit(rawptr buffer, usize size)
|
||||||
|
{
|
||||||
|
Arena *arena = (Arena *)buffer;
|
||||||
|
buffer = PtrAdd(buffer, ARENA_HEADER_SIZE);
|
||||||
|
|
||||||
|
arena->buffer = (u8 *)buffer;
|
||||||
|
arena->length = size;
|
||||||
|
arena->pos = 0;
|
||||||
|
|
||||||
|
return arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Arena *
|
||||||
|
ArenaCreate(usize size)
|
||||||
|
{
|
||||||
|
u8 *mem = (u8 *)pMemAllocZeroed(size);
|
||||||
|
return ArenaInit(mem, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Arena *
|
||||||
|
ArenaCreateDebug(usize size, u32 init_line_no)
|
||||||
|
{
|
||||||
|
u8 *mem = (u8 *)pMemAllocZeroed(size);
|
||||||
|
return ArenaInitDebug(mem, size, init_line_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: investigate overflows when out of memory because something bad is going on
|
||||||
|
static rawptr
|
||||||
|
ArenaAllocAlign(Arena *arena, usize size, usize align)
|
||||||
|
{
|
||||||
|
rawptr ptr = NULL;
|
||||||
|
|
||||||
|
uintptr curr_ptr = (uintptr)arena->buffer + (uintptr)arena->pos;
|
||||||
|
uintptr offset = AlignPow2(curr_ptr, align);
|
||||||
|
offset -= (uintptr)arena->buffer;
|
||||||
|
|
||||||
|
if (offset+size <= arena->length)
|
||||||
|
{
|
||||||
|
ptr = &arena->buffer[offset];
|
||||||
|
arena->pos = offset+size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printfln("Out of memory: %d", arena->init_line_no);
|
||||||
|
Assert(0, "Memory Failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rawptr
|
||||||
|
ArenaAlloc(Arena *arena, usize size)
|
||||||
|
{
|
||||||
|
return ArenaAllocAlign(arena, size, DEFAULT_ALIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ArenaFree(Arena *arena)
|
||||||
|
{
|
||||||
|
arena->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ArenaFreeZeroed(Arena *arena)
|
||||||
|
{
|
||||||
|
MemZero(arena->buffer, arena->pos);
|
||||||
|
ArenaFree(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DeallocArena(Arena *arena)
|
||||||
|
{
|
||||||
|
pMemFree(arena, arena->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Arena *
|
||||||
|
ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no)
|
||||||
|
{
|
||||||
|
Arena *arena = ArenaInit(buffer, size);
|
||||||
|
arena->init_line_no = init_line_no;
|
||||||
|
return arena;
|
||||||
|
}
|
||||||
30
src/alloc.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ::Types::
|
||||||
|
|
||||||
|
constexpr usize ARENA_HEADER_SIZE = 32;
|
||||||
|
|
||||||
|
typedef struct Arena
|
||||||
|
{
|
||||||
|
u8 *buffer;
|
||||||
|
usize length;
|
||||||
|
usize pos;
|
||||||
|
u32 init_line_no;
|
||||||
|
} Arena;
|
||||||
|
|
||||||
|
// ::Allocator::Util::Header::
|
||||||
|
|
||||||
|
static inline usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size);
|
||||||
|
static inline usize CalcPadding(uintptr ptr, uintptr alignment);
|
||||||
|
|
||||||
|
// ::Allocator::Arena::Header::
|
||||||
|
|
||||||
|
static Arena *ArenaInit(rawptr buffer, usize size);
|
||||||
|
static Arena *ArenaCreate(usize size);
|
||||||
|
static Arena *ArenaCreateDebug(usize size, u32 init_line_no);
|
||||||
|
static Arena *ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no);
|
||||||
|
static rawptr ArenaAllocAlign(Arena *arena, usize size, usize align);
|
||||||
|
static rawptr ArenaAlloc(Arena *arena, usize size);
|
||||||
|
static void ArenaFree(Arena *arena);
|
||||||
|
static void ArenaFreeZeroed(Arena *arena);
|
||||||
|
static void DeallocArena(Arena *arena);
|
||||||
482
src/assets.cpp
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
// ::Assets::Constants::Start::
|
||||||
|
|
||||||
|
const u32 M3D_FILE = CreateMagicValue('3', 'D', 'M', 'O');
|
||||||
|
const u32 M3D_PREVIEW = CreateMagicValue('P', 'R', 'V', 'W');
|
||||||
|
const u32 M3D_HEAD = CreateMagicValue('H', 'E', 'A', 'D');
|
||||||
|
const u32 M3D_END_CHUNK = CreateMagicValue('O', 'M', 'D', '3');
|
||||||
|
const u32 M3D_ASSET = CreateMagicValue('A', 'S', 'E', 'T');
|
||||||
|
const u32 M3D_ACTION = CreateMagicValue('A', 'C', 'T', 'N');
|
||||||
|
const u32 M3D_COL_MAP = CreateMagicValue('C', 'M', 'A', 'P');
|
||||||
|
const u32 M3D_TEX_MAP = CreateMagicValue('T', 'M', 'A', 'P');
|
||||||
|
const u32 M3D_VERT = CreateMagicValue('V', 'R', 'T', 'S');
|
||||||
|
const u32 M3D_BONE = CreateMagicValue('B', 'O', 'N', 'E');
|
||||||
|
const u32 M3D_MAT = CreateMagicValue('M', 'T', 'R', 'L');
|
||||||
|
const u32 M3D_PROCEDURAL = CreateMagicValue('P', 'R', 'O', 'C');
|
||||||
|
const u32 M3D_MESH = CreateMagicValue('M', 'E', 'S', 'H');
|
||||||
|
const u32 M3D_VOXEL_TYPE = CreateMagicValue('V', 'O', 'X', 'T');
|
||||||
|
const u32 M3D_VOXEL_DATA = CreateMagicValue('V', 'O', 'X', 'D');
|
||||||
|
const u32 M3D_SHAPE = CreateMagicValue('S', 'H', 'P', 'E');
|
||||||
|
const u32 M3D_LABEL = CreateMagicValue('L', 'B', 'L', 'S');
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Constants::Start::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Globals::Start::
|
||||||
|
|
||||||
|
#ifndef BUILD_PACKER
|
||||||
|
u8 ASSET_PACK[] =
|
||||||
|
{
|
||||||
|
#embed "../build/assets.sgp"
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
u8 ASSET_PACK[] = {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static FileHeader File_Header = {0};
|
||||||
|
|
||||||
|
static AssetFile Asset_Info[ASSET_MAX];
|
||||||
|
static Asset Asset_Data[ASSET_MAX];
|
||||||
|
|
||||||
|
static b32 ASSET_HEADER_LOADED = false;
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Global::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Init::Functions::Start::
|
||||||
|
|
||||||
|
static void apInit()
|
||||||
|
{
|
||||||
|
MemCpy(&File_Header, ASSET_PACK, sizeof(FileHeader));
|
||||||
|
|
||||||
|
Assert(File_Header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic value is incorrect");
|
||||||
|
Assert(File_Header.version == FILE_VERSION, "Asset file version mismatch");
|
||||||
|
|
||||||
|
MemCpy(Asset_Info, &ASSET_PACK[File_Header.asset_offset], sizeof(AssetFile) * File_Header.asset_counts);
|
||||||
|
|
||||||
|
ASSET_HEADER_LOADED = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Assets::Init::Functions::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Loading::Functions::Start::
|
||||||
|
|
||||||
|
static Asset *
|
||||||
|
apAssetSearch(u64 hash)
|
||||||
|
{
|
||||||
|
Asset *asset = NULL;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < ASSET_MAX; i++)
|
||||||
|
{
|
||||||
|
if (asset == NULL && Asset_Data[i].hash == 0)
|
||||||
|
{
|
||||||
|
asset = Asset_Data + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash == Asset_Data[i].hash)
|
||||||
|
{
|
||||||
|
asset = Asset_Data + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Asset
|
||||||
|
apLoadWithHash(u64 hash)
|
||||||
|
{
|
||||||
|
if (!ASSET_HEADER_LOADED)
|
||||||
|
{
|
||||||
|
apInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Asset *asset = apAssetSearch(hash);
|
||||||
|
AssetFile file_info = {0};
|
||||||
|
|
||||||
|
if (asset->bytes == NULL)
|
||||||
|
{
|
||||||
|
for (u64 i = 0; i < ASSET_MAX; i++)
|
||||||
|
{
|
||||||
|
if (hash == Asset_Info[i].hash)
|
||||||
|
{
|
||||||
|
file_info = Asset_Info[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_info.hash != 0)
|
||||||
|
{
|
||||||
|
asset->hash = hash;
|
||||||
|
asset->type = file_info.type;
|
||||||
|
|
||||||
|
u8 *bytes = (u8 *)malloc(file_info.len);
|
||||||
|
MemCpy(bytes, &ASSET_PACK[file_info.data_offset], file_info.len);
|
||||||
|
|
||||||
|
if (file_info.type == AT_MODEL)
|
||||||
|
{
|
||||||
|
asset->model = apParseModel(bytes);
|
||||||
|
asset->model_meta = file_info.model_meta;
|
||||||
|
free(bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asset->len = file_info.len;
|
||||||
|
asset->bytes = bytes;
|
||||||
|
asset->texture_meta = file_info.texture_meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Asset
|
||||||
|
apLoad(c8 *str)
|
||||||
|
{
|
||||||
|
u64 hash = HashFromString(String8CStr(str));
|
||||||
|
return apLoadWithHash(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Asset
|
||||||
|
apLoadS8(String8 str)
|
||||||
|
{
|
||||||
|
return apLoad(str.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apUnloadWithHash(u64 hash)
|
||||||
|
{
|
||||||
|
Asset *asset = apAssetSearch(hash);
|
||||||
|
|
||||||
|
if (asset->bytes != NULL)
|
||||||
|
{
|
||||||
|
if (asset->type == AT_MODEL)
|
||||||
|
{
|
||||||
|
apFreeModel(asset->model);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(asset->bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
asset->bytes = NULL;
|
||||||
|
asset->type = AT_NONE;
|
||||||
|
asset->len = 0;
|
||||||
|
asset->hash = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apUnload(c8 *str)
|
||||||
|
{
|
||||||
|
u64 hash = HashFromString(String8CStr(str));
|
||||||
|
apUnloadWithHash(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apUnloadS8(String8 str)
|
||||||
|
{
|
||||||
|
apUnload(str.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
apAssetIndex(c8 *str)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static Asset apLoadTexture(TextureAsset asset_id)
|
||||||
|
{
|
||||||
|
if (!ASSET_HEADER_LOADED)
|
||||||
|
{
|
||||||
|
apInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(asset_id < i32(TEXTURE_ASSET_MAX), "LoadTextureAsset failure: asset_id is higher than TEXTURE_ASSET_MAX");
|
||||||
|
|
||||||
|
Asset asset = Texture_Asset_Lookup[asset_id];
|
||||||
|
|
||||||
|
if (asset.bytes == NULL)
|
||||||
|
{
|
||||||
|
AssetFile *asset_info = Texture_Assets + asset_id;
|
||||||
|
u8 *img = malloc(asset_info->len);
|
||||||
|
MemCpy(img, &ASSET_PACK[asset_info->data_offset], asset_info->len);
|
||||||
|
|
||||||
|
asset.bytes = img;
|
||||||
|
asset.len = asset_info->len;
|
||||||
|
|
||||||
|
Texture_Asset_Lookup[asset_id] = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Asset apLoadShader(ShaderAsset asset_id)
|
||||||
|
{
|
||||||
|
if (!ASSET_HEADER_LOADED)
|
||||||
|
{
|
||||||
|
apInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(asset_id < SHADER_ASSET_MAX, "LoadShaderAsset failure: asset_id is higher than SHADER_ASSET_MAX");
|
||||||
|
|
||||||
|
Asset asset = Shader_Asset_Lookup[asset_id];
|
||||||
|
if (asset.bytes == NULL)
|
||||||
|
{
|
||||||
|
AssetFile *asset_info = Shader_Assets + asset_id;
|
||||||
|
|
||||||
|
asset.bytes = malloc(asset_info->len);
|
||||||
|
MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len);
|
||||||
|
asset.len = asset_info->len;
|
||||||
|
Shader_Asset_Lookup[asset_id] = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Asset apLoadModel(ModelAsset asset_id)
|
||||||
|
{
|
||||||
|
if (!ASSET_HEADER_LOADED)
|
||||||
|
{
|
||||||
|
apInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(asset_id < MODEL_ASSET_MAX, "apLoadModel failure: asset_id is higher than MODEL_ASSET_MAX");
|
||||||
|
|
||||||
|
Asset asset = Model_Asset_Lookup[asset_id];
|
||||||
|
if (asset.bytes == NULL)
|
||||||
|
{
|
||||||
|
AssetFile *asset_info = Model_Assets + asset_id;
|
||||||
|
|
||||||
|
u8 *bytes = malloc(asset_info->len);
|
||||||
|
MemCpy(bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len);
|
||||||
|
asset.model = apParseModel(bytes);
|
||||||
|
|
||||||
|
free(bytes);
|
||||||
|
|
||||||
|
Model_Asset_Lookup[asset_id] = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TexMeta apGetTextureMeta(TextureAsset asset_id)
|
||||||
|
{
|
||||||
|
AssetFile *asset_file = Texture_Assets + asset_id;
|
||||||
|
return asset_file->texture_meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ModelMeta apGetModelMeta(ModelAsset asset_id)
|
||||||
|
{
|
||||||
|
//AssetFile *asset_file = Model_Assets + asset_id;
|
||||||
|
//return asset_file->model_meta;
|
||||||
|
|
||||||
|
ModelMeta meta = {0};
|
||||||
|
Asset asset = Model_Asset_Lookup[asset_id];
|
||||||
|
if (asset.model != NULL)
|
||||||
|
{
|
||||||
|
meta.i_count = asset.model->index.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apUnloadTexture(TextureAsset asset_id)
|
||||||
|
{
|
||||||
|
Asset *asset = Texture_Asset_Lookup + asset_id;
|
||||||
|
if (asset->bytes != NULL)
|
||||||
|
{
|
||||||
|
free(asset->bytes);
|
||||||
|
asset->bytes = NULL;
|
||||||
|
asset->len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apUnloadShader(ShaderAsset asset_id)
|
||||||
|
{
|
||||||
|
Asset *asset = Shader_Asset_Lookup + asset_id;
|
||||||
|
if (asset->bytes != NULL)
|
||||||
|
{
|
||||||
|
free(asset->bytes);
|
||||||
|
asset->bytes = NULL;
|
||||||
|
asset->len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apUnloadModel(ModelAsset asset_id)
|
||||||
|
{
|
||||||
|
Asset *asset = Model_Asset_Lookup + asset_id;
|
||||||
|
if (asset->bytes != NULL)
|
||||||
|
{
|
||||||
|
free(asset->bytes);
|
||||||
|
asset->bytes = NULL;
|
||||||
|
asset->len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ::Assets::Loading::Functions::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Images::Start::
|
||||||
|
|
||||||
|
static Image
|
||||||
|
apLoadImage(u8 *data, u64 len)
|
||||||
|
{
|
||||||
|
Image image = {0};
|
||||||
|
image.w = -1;
|
||||||
|
image.h = -1;
|
||||||
|
image.ch = -1;
|
||||||
|
|
||||||
|
int ch = 4;
|
||||||
|
int w, h, has_ch;
|
||||||
|
u8 *bytes = stbi_load_from_memory(data, len, &w, &h, &has_ch, ch);
|
||||||
|
if (w <= 0 || h <= 0 || has_ch <= 0)
|
||||||
|
{
|
||||||
|
Printfln("apLoadImage failure: %s", stbi_failure_reason());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
image.data = bytes;
|
||||||
|
image.w = w;
|
||||||
|
image.h = h;
|
||||||
|
image.ch = has_ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apFreeImage(Image *image)
|
||||||
|
{
|
||||||
|
if (image->data != NULL)
|
||||||
|
{
|
||||||
|
stbi_image_free(image->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Assets::Images::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Assets::Models::Functions::Start::
|
||||||
|
|
||||||
|
static inline b32 apChkMag(u32 *magic, u32 expected)
|
||||||
|
{
|
||||||
|
return *magic == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: parse this without the SDK
|
||||||
|
static Model *
|
||||||
|
apParseModel(u8 *data)
|
||||||
|
{
|
||||||
|
m3d_t *m3d = m3d_load(data, NULL, NULL, NULL);
|
||||||
|
Assert(m3d != NULL, "model returned is NULL");
|
||||||
|
|
||||||
|
Printfln("model: %s", m3d->name);
|
||||||
|
Printfln("numcmap: %llu", m3d->numcmap);
|
||||||
|
Printfln("numtmap: %llu", m3d->numtmap);
|
||||||
|
Printfln("numtexture: %llu", m3d->numtexture);
|
||||||
|
Printfln("numbone: %llu", m3d->numbone);
|
||||||
|
Printfln("numvertex: %llu", m3d->numvertex);
|
||||||
|
Printfln("numskin: %llu", m3d->numskin);
|
||||||
|
Printfln("nummaterial: %llu", m3d->nummaterial);
|
||||||
|
Printfln("numface: %llu", m3d->numface);
|
||||||
|
Printfln("numvoxtype: %llu", m3d->numvoxtype);
|
||||||
|
Printfln("numvoxel: %llu", m3d->numvoxel);
|
||||||
|
Printfln("numshape: %llu", m3d->numshape);
|
||||||
|
Printfln("numlabel: %llu", m3d->numlabel);
|
||||||
|
Printfln("numaction: %llu", m3d->numaction);
|
||||||
|
Printfln("numinlined: %llu", m3d->numinlined);
|
||||||
|
Printfln("numextra: %llu", m3d->numextra);
|
||||||
|
|
||||||
|
Model *model = (Model *)malloc(sizeof(Model));
|
||||||
|
|
||||||
|
model->vertex.count = u64(m3d->numvertex);
|
||||||
|
model->vertex.data = (Vertex *)malloc(sizeof(Vertex) * model->vertex.count);
|
||||||
|
|
||||||
|
model->index.count = u64(m3d->numface * 3);
|
||||||
|
model->index.data = (u32 *)malloc(sizeof(u32) * model->index.count);
|
||||||
|
|
||||||
|
model->material.count = u64(m3d->nummaterial);
|
||||||
|
model->material.data = (Material *)malloc(sizeof(Material) * m3d->nummaterial);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < m3d->nummaterial; i += 1)
|
||||||
|
{
|
||||||
|
for (u64 j = 0; j < m3d->material[i].numprop; j += 1)
|
||||||
|
{
|
||||||
|
switch (m3d->material[i].prop[j].type)
|
||||||
|
{
|
||||||
|
case m3dp_Kd:
|
||||||
|
{
|
||||||
|
U32ColToVec4(&model->material.data[i].color, m3d->material[i].prop[j].value.color);
|
||||||
|
} break;
|
||||||
|
case m3dp_Ka:
|
||||||
|
{
|
||||||
|
U32ColToVec4(&model->material.data[i].ambient, m3d->material[i].prop[j].value.color);
|
||||||
|
} break;
|
||||||
|
case m3dp_Ks:
|
||||||
|
{
|
||||||
|
U32ColToVec4(&model->material.data[i].specular, m3d->material[i].prop[j].value.color);
|
||||||
|
} break;
|
||||||
|
case m3dp_Ke:
|
||||||
|
{
|
||||||
|
U32ColToVec4(&model->material.data[i].emission, m3d->material[i].prop[j].value.color);
|
||||||
|
} break;
|
||||||
|
case m3dp_Ns:
|
||||||
|
{
|
||||||
|
model->material.data[i].shininess = m3d->material[i].prop[j].value.fnum;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < m3d->numinlined; i += 1)
|
||||||
|
{
|
||||||
|
Image texture = apLoadImage(m3d->inlined[i].data, m3d->inlined[i].length);
|
||||||
|
Assert(texture.data != NULL, "Image is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: replace
|
||||||
|
for (u64 i = 0; i < m3d->numvertex; i += 1)
|
||||||
|
{
|
||||||
|
model->vertex.data[i].pos.x = m3d->vertex[i].x;
|
||||||
|
model->vertex.data[i].pos.y = m3d->vertex[i].y;
|
||||||
|
model->vertex.data[i].pos.z = m3d->vertex[i].z;
|
||||||
|
model->vertex.data[i].pos.w = m3d->vertex[i].w;
|
||||||
|
|
||||||
|
model->vertex.data[i].col.packed = m3d->vertex[i].color;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0, j = 0; i < m3d->numface; i += 1, j += 3)
|
||||||
|
{
|
||||||
|
model->index.data[j] = m3d->face[i].vertex[0];
|
||||||
|
model->index.data[j+1] = m3d->face[i].vertex[1];
|
||||||
|
model->index.data[j+2] = m3d->face[i].vertex[2];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
m3d_free(m3d);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apFreeModel(Model *model)
|
||||||
|
{
|
||||||
|
free(model->vertex.data);
|
||||||
|
free(model->index.data);
|
||||||
|
free(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Assets::Models::Functions::End::
|
||||||
|
|
||||||
164
src/assets.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ::Assets::Macros::Header::
|
||||||
|
|
||||||
|
#define FILE_VERSION 3U
|
||||||
|
|
||||||
|
#define CreateMagicValue(a, b, c, d) ((u32)(d << 24) | (u32)(c << 16) | (u32)(b << 8) | (u32)(a))
|
||||||
|
|
||||||
|
// ::Assets::Globals::Header::
|
||||||
|
#include "codegen_assets.h"
|
||||||
|
|
||||||
|
// ::Assets::Types::Header::
|
||||||
|
|
||||||
|
typedef struct Vertex
|
||||||
|
{
|
||||||
|
f32 v_x, v_y, v_z;
|
||||||
|
f32 n_x, n_y, n_z;
|
||||||
|
f32 uv_x, uv_y;
|
||||||
|
u32 color;
|
||||||
|
} Vertex;
|
||||||
|
|
||||||
|
typedef struct Image
|
||||||
|
{
|
||||||
|
rawptr data;
|
||||||
|
i32 w;
|
||||||
|
i32 h;
|
||||||
|
i32 ch;
|
||||||
|
} Image;
|
||||||
|
|
||||||
|
typedef struct Material
|
||||||
|
{
|
||||||
|
Vec4 color;
|
||||||
|
Vec4 ambient;
|
||||||
|
Vec4 specular;
|
||||||
|
Vec4 emission;
|
||||||
|
f32 shininess;
|
||||||
|
} Material;
|
||||||
|
|
||||||
|
typedef struct ModelIndex
|
||||||
|
{
|
||||||
|
u32 material;
|
||||||
|
u32 start;
|
||||||
|
u32 count;
|
||||||
|
} ModelIndex;
|
||||||
|
|
||||||
|
typedef struct Model
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vertex *data;
|
||||||
|
u64 count;
|
||||||
|
} vertex;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 *data;
|
||||||
|
u64 count;
|
||||||
|
} index;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Material *data;
|
||||||
|
u64 count;
|
||||||
|
} material;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ModelIndex *data;
|
||||||
|
u64 count;
|
||||||
|
} offset;
|
||||||
|
} Model;
|
||||||
|
|
||||||
|
typedef struct TexMeta
|
||||||
|
{
|
||||||
|
u32 w;
|
||||||
|
u32 h;
|
||||||
|
u32 ch;
|
||||||
|
} TexMeta;
|
||||||
|
|
||||||
|
typedef struct ModelMeta
|
||||||
|
{
|
||||||
|
u64 i_count;
|
||||||
|
} ModelMeta;
|
||||||
|
|
||||||
|
typedef struct AssetTag
|
||||||
|
{
|
||||||
|
u32 tag_id;
|
||||||
|
f32 value;
|
||||||
|
} AssetTag;
|
||||||
|
|
||||||
|
typedef enum AssetType_e
|
||||||
|
{
|
||||||
|
AT_NONE,
|
||||||
|
AT_SHADER,
|
||||||
|
AT_TEXTURE,
|
||||||
|
AT_MODEL,
|
||||||
|
} AssetType;
|
||||||
|
|
||||||
|
typedef struct Asset
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
const char *cstr;
|
||||||
|
u8 *bytes;
|
||||||
|
Model *model;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TexMeta texture_meta;
|
||||||
|
ModelMeta model_meta;
|
||||||
|
};
|
||||||
|
u64 hash;
|
||||||
|
u64 len;
|
||||||
|
AssetType type;
|
||||||
|
} Asset;
|
||||||
|
|
||||||
|
typedef struct AssetFile
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
TexMeta texture_meta;
|
||||||
|
ModelMeta model_meta;
|
||||||
|
};
|
||||||
|
u64 hash;
|
||||||
|
u64 data_offset;
|
||||||
|
u64 len;
|
||||||
|
AssetType type;
|
||||||
|
} AssetFile;
|
||||||
|
|
||||||
|
typedef struct FileHeader
|
||||||
|
{
|
||||||
|
u32 magic_num;
|
||||||
|
u32 version;
|
||||||
|
u32 asset_counts;
|
||||||
|
u64 asset_offset;
|
||||||
|
} FileHeader;
|
||||||
|
|
||||||
|
// ::Assets::Init::Functions::Header::
|
||||||
|
|
||||||
|
static void apInit();
|
||||||
|
|
||||||
|
// ::Assets::Loading::Functions::Header::
|
||||||
|
|
||||||
|
static Asset apLoad(c8 *str);
|
||||||
|
static Asset apLoadS8(String8 str);
|
||||||
|
static Asset apLoadWithHash(u64 hash);
|
||||||
|
static void apUnload(c8 *str);
|
||||||
|
static void apUnloadS8(String8 str);
|
||||||
|
static void apUnloadWithHash(u64 hash);
|
||||||
|
static u64 apAssetIndex(c8 *str);
|
||||||
|
static Asset *apAssetSearch(u64 hash);
|
||||||
|
|
||||||
|
// ::Assets::Util::Functions::Header::
|
||||||
|
|
||||||
|
// TODO(MA): Implement async asset handling
|
||||||
|
static inline b32 apMarkUnloaded(c8 *str);
|
||||||
|
static inline void apMarkLoaded(c8 *str);
|
||||||
|
|
||||||
|
// ::Assets::Images::Header::
|
||||||
|
|
||||||
|
static Image apLoadImage(rawptr data, u64 len);
|
||||||
|
static void apFreeImage(Image *image);
|
||||||
|
|
||||||
|
// ::Assets::Models::Functions::Header::
|
||||||
|
|
||||||
|
static Model *apParseModel(u8 *data);
|
||||||
|
static void apFreeModel(Model *model);
|
||||||
92
src/base_types.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# include <cstddef>
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ::BaseTypes::
|
||||||
|
|
||||||
|
typedef int8_t i8;
|
||||||
|
typedef int16_t i16;
|
||||||
|
typedef int32_t i32;
|
||||||
|
typedef int64_t i64;
|
||||||
|
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
typedef char c8;
|
||||||
|
|
||||||
|
typedef intptr_t intptr;
|
||||||
|
typedef uintptr_t uintptr;
|
||||||
|
|
||||||
|
typedef float f32;
|
||||||
|
typedef double f64;
|
||||||
|
|
||||||
|
typedef uint8_t b8;
|
||||||
|
typedef uint32_t b32;
|
||||||
|
|
||||||
|
typedef void * rawptr;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
typedef ssize_t isize;
|
||||||
|
typedef size_t usize;
|
||||||
|
#elif _WIN64
|
||||||
|
typedef int64_t isize;
|
||||||
|
typedef u64 usize;
|
||||||
|
#elif _WIN32
|
||||||
|
typedef i32 isize;
|
||||||
|
typedef u32 usize;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct String8
|
||||||
|
{
|
||||||
|
c8 *value;
|
||||||
|
u64 len;
|
||||||
|
} String8;
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct { f32 x, y, z, w; };
|
||||||
|
struct { f32 r, g, b, a; };
|
||||||
|
} Vec4;
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct { u8 x, y, z, w; };
|
||||||
|
struct { u8 r, g, b, a; };
|
||||||
|
struct { u32 packed; };
|
||||||
|
} U8Vec4;
|
||||||
|
|
||||||
|
// ::Macros::
|
||||||
|
|
||||||
|
#define i8(x) ((i8)(x))
|
||||||
|
#define i16(x) ((i16)(x))
|
||||||
|
#define i32(x) ((i32)(x))
|
||||||
|
#define i64(x) ((i64)(x))
|
||||||
|
|
||||||
|
#define u8(x) ((u8)(x))
|
||||||
|
#define u16(x) ((u16)(x))
|
||||||
|
#define u32(x) ((u32)(x))
|
||||||
|
#define u64(x) ((u64)(x))
|
||||||
|
|
||||||
|
#define c8(x) ((c8)(x))
|
||||||
|
#define c8ptr(x) ((c8 *)(x))
|
||||||
|
#define u8ptr(x) ((u8 *)(x))
|
||||||
|
#define i8ptr(x) ((i8 *)(x))
|
||||||
|
|
||||||
|
#define intptr(x) ((intptr)(x))
|
||||||
|
#define uintptr(x) ((uintptr)(x))
|
||||||
|
|
||||||
|
#define f32(x) ((f32)(x))
|
||||||
|
#define f64(x) ((f64)(x))
|
||||||
|
|
||||||
|
#define rawptr(x) ((rawptr)(x))
|
||||||
|
|
||||||
|
#define cast(T, x) ((T)(x))
|
||||||
|
|
||||||
|
#define isizeof(T) ((isize)(sizeof(T)))
|
||||||
172
src/codegen.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#include "codegen.h"
|
||||||
|
|
||||||
|
#include "os.cpp"
|
||||||
|
|
||||||
|
#include "xxhash/xxhash.c"
|
||||||
|
|
||||||
|
u64
|
||||||
|
WriteArrayToFile(Arena *arena, pFile file, String8 array_name, rawptr elements, u32 count, String8 type, u64 offset)
|
||||||
|
{
|
||||||
|
b32 is_string = StrEq(type.value, "c8 *");
|
||||||
|
c8 *decl = MakeArray(arena, c8, 2048);
|
||||||
|
i32 decl_len = SPrintf(decl, 2048, "static %s\n%s[] = \n{\n\t", type.value, array_name.value);
|
||||||
|
String8 result = {
|
||||||
|
.value = decl,
|
||||||
|
.len = u64(decl_len),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (is_string)
|
||||||
|
{
|
||||||
|
String8 *strs = (String8 *)elements;
|
||||||
|
for (u32 i = 0; i < count; i += 1)
|
||||||
|
{
|
||||||
|
const c8 *f = i == count-1 ? "\"%s\"," : "\"%s\",\n\t";
|
||||||
|
c8 buf[512];
|
||||||
|
decl_len = SPrintf(buf, 512, f, strs[i].value);
|
||||||
|
result = String8Concat(arena, result, MakeString8(buf, decl_len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 *ints = (u64 *)elements;
|
||||||
|
for (u32 i = 0; i < count; i += 1)
|
||||||
|
{
|
||||||
|
const c8 *f = i == count-1 ? "%lluU," : "%lluU,\n\t";
|
||||||
|
c8 buf[512];
|
||||||
|
decl_len = SPrintf(buf, 512, f, ints[i]);
|
||||||
|
result = String8Concat(arena, result, MakeString8(buf, decl_len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = String8Concat(arena, result, String8CStr("\n};\n\n"));
|
||||||
|
|
||||||
|
return pFileWrite(file, offset, result.value, result.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8 *
|
||||||
|
ConvertCStrs(Arena *arena, c8 **strs, u32 count)
|
||||||
|
{
|
||||||
|
String8 *str8s = MakeArray(arena, String8, count);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < count; i += 1)
|
||||||
|
{
|
||||||
|
str8s[i].value = strs[i];
|
||||||
|
str8s[i].len = StrLen(strs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CodeGenAssetLookups(Arena *arena)
|
||||||
|
{
|
||||||
|
pFile file = pFileOpen("../src/codegen_assets.h", pFS_WRITE | pFS_CREATE | pFS_TRUNC);
|
||||||
|
Assert(file > 0, "CodeGenAssetLookups failure: unable to open/create file");
|
||||||
|
|
||||||
|
Assert(pDirNavigate("../assets") == 0, "Unable to navigate to asset directory");
|
||||||
|
|
||||||
|
struct AssetDirInfo {
|
||||||
|
c8 *prefix, *struct_name, *hash_struct_name, *dir, *define;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AssetDirInfo dirs[] = {
|
||||||
|
{
|
||||||
|
.prefix = "shaders/",
|
||||||
|
.struct_name = "g_Shader_Asset_Names",
|
||||||
|
.hash_struct_name = "g_Shader_Asset_Hashes",
|
||||||
|
.dir = "shaders",
|
||||||
|
.define = "SHADER_ASSET",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.prefix = "models/",
|
||||||
|
.struct_name = "g_Model_Asset_Names",
|
||||||
|
.hash_struct_name = "g_Model_Asset_Hashes",
|
||||||
|
.dir = "models",
|
||||||
|
.define = "MODEL_ASSET",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.prefix = "textures/",
|
||||||
|
.struct_name = "g_Texture_Asset_Names",
|
||||||
|
.hash_struct_name = "g_Texture_Asset_Hashes",
|
||||||
|
.dir = "textures",
|
||||||
|
.define = "TEXTURE_ASSET",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 total_assets = 0;
|
||||||
|
u64 offset = 0;
|
||||||
|
u32 dir_count = sizeof(dirs) / sizeof(struct AssetDirInfo);
|
||||||
|
for (u32 i = 0; i < dir_count; i += 1)
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate(dirs[i].dir) == 0, "Unable to navigate to asset sub directory.");
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
|
c8 **cstrs = pDirGetFileNames(arena, &count);
|
||||||
|
u64 *hashes = MakeArray(arena, u64, count);
|
||||||
|
String8 *strs = ConvertCStrs(arena, cstrs, count);
|
||||||
|
|
||||||
|
for (u32 j = 0; j < count; j += 1)
|
||||||
|
{
|
||||||
|
strs[j] = String8Concat(arena, String8CStr(dirs[i].prefix), strs[j]);
|
||||||
|
i64 offset = String8FindLast(strs[j], '.');
|
||||||
|
hashes[j] = XXH3_64bits_withSeed(strs[j].value, offset, HASH_SEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += WriteArrayToFile(
|
||||||
|
arena,
|
||||||
|
file,
|
||||||
|
String8CStr(dirs[i].struct_name),
|
||||||
|
strs,
|
||||||
|
count,
|
||||||
|
String8CStr("c8 *"),
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
|
||||||
|
offset += WriteArrayToFile(
|
||||||
|
arena,
|
||||||
|
file,
|
||||||
|
String8CStr(dirs[i].hash_struct_name),
|
||||||
|
hashes,
|
||||||
|
count,
|
||||||
|
String8CStr("u64"),
|
||||||
|
offset
|
||||||
|
);
|
||||||
|
|
||||||
|
c8 buf[256];
|
||||||
|
i32 decl_len = SPrintf(buf, 256, "#define %s_MAX %lluU\n\n#define %s %dU\n\n", dirs[i].define, count, dirs[i].define, i);
|
||||||
|
|
||||||
|
offset += pFileWrite(file, offset, buf, decl_len);
|
||||||
|
|
||||||
|
total_assets += count;
|
||||||
|
|
||||||
|
if (i == dir_count-1)
|
||||||
|
{
|
||||||
|
decl_len = SPrintf(buf, 256, "#define ASSET_MAX %lluU\n\n#define RENDERER_ASSET_MAX (ASSET_MAX - SHADER_ASSET_MAX)\n\n#define ASSET_TYPE_MAX %dU\n\n", total_assets, i+1);
|
||||||
|
pFileWrite(file, offset, buf, decl_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(pDirNavigate("..") == 0, "CodeGenAssetLookups failure: unable to move back to build directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
pFileClose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, c8 **argv)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
_set_fmode(_O_BINARY);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pDirIsVisible("build"))
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate("./build") == 0, "Unable to change to build directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mem = pMemAllocZeroed(GB(1));
|
||||||
|
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
|
||||||
|
|
||||||
|
CodeGenAssetLookups(arena);
|
||||||
|
}
|
||||||
6
src/codegen.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define STG_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
72
src/codegen_assets.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
static c8 *
|
||||||
|
g_Shader_Asset_Names[] =
|
||||||
|
{
|
||||||
|
"shaders/pbr.frag.spv",
|
||||||
|
"shaders/pbr.vert.spv",
|
||||||
|
};
|
||||||
|
|
||||||
|
static u64
|
||||||
|
g_Shader_Asset_Hashes[] =
|
||||||
|
{
|
||||||
|
2230071466542309169U,
|
||||||
|
8518761701216801634U,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHADER_ASSET_MAX 2U
|
||||||
|
|
||||||
|
#define SHADER_ASSET 0U
|
||||||
|
|
||||||
|
static c8 *
|
||||||
|
g_Model_Asset_Names[] =
|
||||||
|
{
|
||||||
|
"models/cube.m3d",
|
||||||
|
"models/test_char.m3d",
|
||||||
|
"models/yoda.m3d",
|
||||||
|
};
|
||||||
|
|
||||||
|
static u64
|
||||||
|
g_Model_Asset_Hashes[] =
|
||||||
|
{
|
||||||
|
16487010975852376380U,
|
||||||
|
13826959199295087925U,
|
||||||
|
4559395153940738542U,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MODEL_ASSET_MAX 3U
|
||||||
|
|
||||||
|
#define MODEL_ASSET 1U
|
||||||
|
|
||||||
|
static c8 *
|
||||||
|
g_Texture_Asset_Names[] =
|
||||||
|
{
|
||||||
|
"textures/ham_smoke.png",
|
||||||
|
"textures/cheesoid.png",
|
||||||
|
"textures/hog.jpg",
|
||||||
|
"textures/patamon.png",
|
||||||
|
"textures/pattermon.png",
|
||||||
|
"textures/hamster.png",
|
||||||
|
"textures/purplemon.png",
|
||||||
|
};
|
||||||
|
|
||||||
|
static u64
|
||||||
|
g_Texture_Asset_Hashes[] =
|
||||||
|
{
|
||||||
|
15457434128510259736U,
|
||||||
|
12443444479937967236U,
|
||||||
|
5538438794723924882U,
|
||||||
|
16650761267170532297U,
|
||||||
|
11718504567089932798U,
|
||||||
|
7627422980398294448U,
|
||||||
|
14316598952102237724U,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEXTURE_ASSET_MAX 7U
|
||||||
|
|
||||||
|
#define TEXTURE_ASSET 2U
|
||||||
|
|
||||||
|
#define ASSET_MAX 12U
|
||||||
|
|
||||||
|
#define RENDERER_ASSET_MAX (ASSET_MAX - SHADER_ASSET_MAX)
|
||||||
|
|
||||||
|
#define ASSET_TYPE_MAX 3U
|
||||||
|
|
||||||
14
src/entry_linux.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "entry_linux.h"
|
||||||
|
|
||||||
|
#include "os_linux.cpp"
|
||||||
|
|
||||||
|
#include "renderer.cpp"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Renderer renderer;
|
||||||
|
Init(&renderer);
|
||||||
|
|
||||||
|
while (RunCycle(&renderer));
|
||||||
|
}
|
||||||
7
src/entry_linux.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "os_linux.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv);
|
||||||
7
src/os.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# include "os_linux.cpp"
|
||||||
|
#elif _WIN32
|
||||||
|
# include "os_win32.cpp"
|
||||||
|
#endif
|
||||||
7
src/os.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
# include "os_linux.h"
|
||||||
|
#elif _WIN32
|
||||||
|
# include "os_win32.h"
|
||||||
|
#endif
|
||||||
466
src/os_linux.cpp
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
#include "os_linux.h"
|
||||||
|
|
||||||
|
// ::Constants::
|
||||||
|
static b32 g_Global_Quit = false;
|
||||||
|
|
||||||
|
// TODO: figure out a way to get appropriate defaults
|
||||||
|
static constexpr i32 WINDOW_WIDTH = 1280;
|
||||||
|
static constexpr i32 WINDOW_HEIGHT = 720;
|
||||||
|
|
||||||
|
// ::Misc::Impl::Start::
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pSyscallErrCheck(void *ptr)
|
||||||
|
{
|
||||||
|
return (isize)ptr == SYS_ERR ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Misc::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::Console::Impl::Start::
|
||||||
|
|
||||||
|
static i32
|
||||||
|
pWriteStdOut(void * buf, i32 len)
|
||||||
|
{
|
||||||
|
return (i32)write(STDOUT, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
pWriteStdErr(void * buf, i32 len)
|
||||||
|
{
|
||||||
|
return (i32)write(STDERR, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
SPrintf(char *buf, int len, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
int sprf_res = stbsp_vsnprintf(buf, len, fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
return sprf_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
Printf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
i32 result = PrintfVargs(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
Printfln(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
i32 result = PrintflnVargs(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
EPrintf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
i32 result = EPrintfVargs(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
EPrint(void *str)
|
||||||
|
{
|
||||||
|
return pWriteStdErr(str, StrLen((const char*)str));
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
EPrintfVargs(const char *fmt, va_list arg)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
|
||||||
|
|
||||||
|
if (sprf_res < 0) return sprf_res;
|
||||||
|
|
||||||
|
return EPrint(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
PrintfVargs(const char *fmt, va_list arg)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1024, fmt, arg);
|
||||||
|
|
||||||
|
i32 pr_res;
|
||||||
|
if (sprf_res < 0)
|
||||||
|
pr_res = sprf_res;
|
||||||
|
else
|
||||||
|
pr_res = pWriteStdOut(&buffer, sprf_res);
|
||||||
|
|
||||||
|
return pr_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32
|
||||||
|
PrintflnVargs(const char *fmt, va_list arg)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
|
||||||
|
int sprf_res = stbsp_vsnprintf(&buffer[0], 1023, fmt, arg);
|
||||||
|
|
||||||
|
i32 pr_res;
|
||||||
|
if (sprf_res < 0)
|
||||||
|
{
|
||||||
|
pr_res = sprf_res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer[sprf_res] = '\n';
|
||||||
|
buffer[sprf_res+1] = '\0';
|
||||||
|
pr_res = pWriteStdOut(&buffer, sprf_res+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pr_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Console::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::DynLib::Impl::
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pLibraryLoad(const char *name, pLibrary *out_lib)
|
||||||
|
{
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_lib->lib = dlopen(name, RTLD_NOW);
|
||||||
|
if (!out_lib->lib) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn)
|
||||||
|
{
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_fn->fn = dlsym(lib->lib, name);
|
||||||
|
if (!out_fn->fn) {
|
||||||
|
Printf("unable to find function\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::MemAlloc::Impl::
|
||||||
|
|
||||||
|
static void *
|
||||||
|
pMemAlloc(size_t size)
|
||||||
|
{
|
||||||
|
void * addr = mmap(
|
||||||
|
NULL,
|
||||||
|
size,
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
MAP_ANON | MAP_PRIVATE,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pSyscallErrCheck(addr)) addr = NULL;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
pMemAllocZeroed(size_t size)
|
||||||
|
{
|
||||||
|
void * ptr = pMemAlloc(size);
|
||||||
|
MemZero(ptr, size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
pMemRealloc(void * ptr, size_t old_size, size_t new_size)
|
||||||
|
{
|
||||||
|
void * addr = mremap(
|
||||||
|
ptr,
|
||||||
|
old_size,
|
||||||
|
new_size,
|
||||||
|
MAP_ANON | MAP_PRIVATE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pSyscallErrCheck(addr)) addr = NULL;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pMemFree(void * ptr, size_t size)
|
||||||
|
{
|
||||||
|
Assert(munmap(ptr, size) == 0, "munmap failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::FileSystem::Impl::Start::
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pDirNavigate(char *dir)
|
||||||
|
{
|
||||||
|
return chdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pFile
|
||||||
|
pFileOpen(char *file_name, pFileAccess acc)
|
||||||
|
{
|
||||||
|
int flags = 0;
|
||||||
|
if (BitEq(acc, pFS_READ) && BitEq(acc, pFS_WRITE))
|
||||||
|
flags = O_RDWR;
|
||||||
|
else if (BitEq(acc, pFS_READ))
|
||||||
|
flags = O_RDONLY;
|
||||||
|
else if (BitEq(acc, pFS_WRITE))
|
||||||
|
flags = O_WRONLY;
|
||||||
|
|
||||||
|
if (BitEq(acc, pFS_TRUNC))
|
||||||
|
{
|
||||||
|
flags |= O_TRUNC;
|
||||||
|
}
|
||||||
|
else if (BitEq(acc, pFS_APPEND))
|
||||||
|
flags |= O_APPEND;
|
||||||
|
|
||||||
|
if (BitEq(acc, pFS_CREATE))
|
||||||
|
flags |= O_CREAT;
|
||||||
|
|
||||||
|
i64 file = open(file_name, flags, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||||
|
if (file < 0)
|
||||||
|
{
|
||||||
|
Printfln("errno: %d", errno);
|
||||||
|
Assert(false, "failed to open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pFileClose(pFile file)
|
||||||
|
{
|
||||||
|
fsync(file);
|
||||||
|
close(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pFileRead(pFile file, u64 offset, void * buf, u64 len)
|
||||||
|
{
|
||||||
|
i64 new_offset = lseek(file, offset, SEEK_SET);
|
||||||
|
if (new_offset < 0)
|
||||||
|
{
|
||||||
|
Printfln("errno: %d", errno);
|
||||||
|
Assert(false, "failed to read file");
|
||||||
|
}
|
||||||
|
return read(file, buf, (size_t)len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pFileWrite(pFile file, u64 offset, void * buf, u64 len)
|
||||||
|
{
|
||||||
|
lseek(file, offset, SEEK_SET);
|
||||||
|
return write(file, buf, (size_t)len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pFileSeek(pFile file, u64 pos)
|
||||||
|
{
|
||||||
|
return (u64)lseek(file, (ssize_t)pos, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pFileLength(pFile file)
|
||||||
|
{
|
||||||
|
ssize_t offset = lseek(file, 0, SEEK_CUR);
|
||||||
|
ssize_t size = lseek(file, 0, SEEK_END);
|
||||||
|
lseek(file, offset, SEEK_SET);
|
||||||
|
|
||||||
|
if (size == -1)
|
||||||
|
size = UINT64_MAX;
|
||||||
|
|
||||||
|
return (u64)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **
|
||||||
|
pDirGetFileNames(Arena *arena, u32 *count)
|
||||||
|
{
|
||||||
|
struct dirent *dir;
|
||||||
|
|
||||||
|
DIR *d = opendir(".");
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
while ((dir = readdir(d)) != NULL)
|
||||||
|
{
|
||||||
|
if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, ".."))
|
||||||
|
*count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char **file_names = MakeArray(arena, c8*, *count);
|
||||||
|
|
||||||
|
d = opendir(".");
|
||||||
|
*count = 0;
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
while ((dir = readdir(d)) != NULL)
|
||||||
|
{
|
||||||
|
if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, ".."))
|
||||||
|
{
|
||||||
|
i32 str_len = StrLen(dir->d_name);
|
||||||
|
file_names[*count] = MakeArray(arena, c8, str_len);
|
||||||
|
MemCpy(file_names[*count], dir->d_name, str_len);
|
||||||
|
*count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char **)file_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pFSIsVisible(char *name, b32 is_dir)
|
||||||
|
{
|
||||||
|
b32 found = false;
|
||||||
|
|
||||||
|
struct dirent *dir;
|
||||||
|
DIR *d = opendir(".");
|
||||||
|
u8 type = is_dir ? DT_DIR : DT_REG;
|
||||||
|
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
while ((dir = readdir(d)) != NULL)
|
||||||
|
{
|
||||||
|
if (StrEq(name, dir->d_name) && dir->d_type == type)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pDirIsVisible(char *dir_name)
|
||||||
|
{
|
||||||
|
return pFSIsVisible(dir_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pFileIsVisible(char *file_name)
|
||||||
|
{
|
||||||
|
return pFSIsVisible(file_name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
pFileCanAccess(char *file_name, pFileAccess file_access)
|
||||||
|
{
|
||||||
|
int a = 0;
|
||||||
|
if (BitEq(file_access, pFS_READ))
|
||||||
|
a |= R_OK;
|
||||||
|
if (BitEq(file_access, pFS_WRITE))
|
||||||
|
a |= W_OK;
|
||||||
|
|
||||||
|
return access(file_name, a) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::FileSystem::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::Profiling::Impl::Start::
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pOSTimerFreq()
|
||||||
|
{
|
||||||
|
return 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64
|
||||||
|
pOSTimerRead()
|
||||||
|
{
|
||||||
|
struct timeval value;
|
||||||
|
gettimeofday(&value, 0);
|
||||||
|
|
||||||
|
return pOSTimerFreq() * u64(value.tv_sec) + u64(value.tv_usec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64
|
||||||
|
pCPUTimerRead()
|
||||||
|
{
|
||||||
|
return __rdtsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Profiling::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::Atomics::Impl::Start::
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pAtomicSignalFenceSeqCst()
|
||||||
|
{
|
||||||
|
__atomic_signal_fence(__ATOMIC_SEQ_CST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
pAtomicFetchSubU32(u32 volatile *ptr, u32 count)
|
||||||
|
{
|
||||||
|
return __atomic_fetch_sub(ptr, count, __ATOMIC_ACQUIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
pAtomicFetchIncrU32(u32 volatile *ptr)
|
||||||
|
{
|
||||||
|
return __atomic_fetch_add(ptr, (u32)1, __ATOMIC_ACQUIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pAtomicIncrU32(u32 volatile *ptr)
|
||||||
|
{
|
||||||
|
__atomic_fetch_add(ptr, (u32)1, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32
|
||||||
|
pAtomicLoadU32(u32 volatile *ptr)
|
||||||
|
{
|
||||||
|
return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pAtomicStoreB32(b32 volatile *ptr, b32 value)
|
||||||
|
{
|
||||||
|
__atomic_store_n(ptr, value, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline b32
|
||||||
|
pAtomicCompareExchangeB32(b32 volatile *ptr, b32 *expected, b32 desired)
|
||||||
|
{
|
||||||
|
return __atomic_compare_exchange_n(ptr, expected, desired, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Atomics::Impl::End::
|
||||||
176
src/os_linux.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include "stb/stb_sprintf.h"
|
||||||
|
#include "stb/stb_image.h"
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
|
||||||
|
#include "xxhash/xxhash.h"
|
||||||
|
#include "xxhash/xxhash.c"
|
||||||
|
|
||||||
|
#define M3D_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include "m3d/m3d.h"
|
||||||
|
|
||||||
|
#include "base_types.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <nmmintrin.h>
|
||||||
|
#include <immintrin.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
// TODO: Replace this eventually:
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
// ::Constants::
|
||||||
|
|
||||||
|
constexpr int SYS_ERR = -1;
|
||||||
|
|
||||||
|
constexpr int STDIN = 0;
|
||||||
|
constexpr int STDOUT = 1;
|
||||||
|
constexpr int STDERR = 2;
|
||||||
|
|
||||||
|
// ::Enums::
|
||||||
|
|
||||||
|
typedef enum e_pFSAccess
|
||||||
|
{
|
||||||
|
pFS_READ = 0x01,
|
||||||
|
pFS_WRITE = 0x02,
|
||||||
|
pFS_TRUNC = 0x04,
|
||||||
|
pFS_APPEND = 0x08,
|
||||||
|
pFS_CREATE = 0x10,
|
||||||
|
} pFSAccess;
|
||||||
|
|
||||||
|
typedef i32 pFileAccess;
|
||||||
|
|
||||||
|
// ::Types::
|
||||||
|
|
||||||
|
typedef int pFile;
|
||||||
|
|
||||||
|
typedef struct pThread
|
||||||
|
{
|
||||||
|
pthread_t handle;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mut;
|
||||||
|
} pThread;
|
||||||
|
|
||||||
|
typedef struct pLibrary
|
||||||
|
{
|
||||||
|
void *lib;
|
||||||
|
} pLibrary;
|
||||||
|
|
||||||
|
typedef struct pFunction
|
||||||
|
{
|
||||||
|
void *fn;
|
||||||
|
} pFunction;
|
||||||
|
|
||||||
|
// ::Macros::
|
||||||
|
|
||||||
|
#define XCB_CHECK_CURRENT_ERROR(window, error, message) do { \
|
||||||
|
error = xcb_request_check(window->connection, cookie); \
|
||||||
|
if (error != NULL) { \
|
||||||
|
EPrintf("%s ERROR CODE: %d\n", message, error->error_code); \
|
||||||
|
free(error); \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define XCB_CHECK_ERROR(window, cookie, error, message) do { \
|
||||||
|
error = xcb_request_check(window->connection, cookie); \
|
||||||
|
XCB_CHECK_CURRENT_ERROR(window, error, message); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
// ::Misc::
|
||||||
|
|
||||||
|
static b32 pSyscallErrCheck(void *ptr);
|
||||||
|
|
||||||
|
// ::Console::
|
||||||
|
|
||||||
|
static i32 pWriteStdOut(void *buf, i32 len);
|
||||||
|
static i32 pWriteStdErr(void *buf, i32 len);
|
||||||
|
|
||||||
|
static i32 SPrintf(char *buf, int len, const char *fmt, ...);
|
||||||
|
static i32 Printf(const char *fmt, ...);
|
||||||
|
static i32 Printfln(const char *fmt, ...);
|
||||||
|
static i32 EPrintf(const char *fmt, ...);
|
||||||
|
|
||||||
|
static i32 PrintfVargs(const char *fmt, va_list arg);
|
||||||
|
static i32 PrintflnVargs(const char *fmt, va_list arg);
|
||||||
|
static i32 EPrintfVargs(const char *fmt, va_list arg);
|
||||||
|
|
||||||
|
// ::DynLib::
|
||||||
|
|
||||||
|
static b32 pLibraryLoad(const char *name, pLibrary *out_lib);
|
||||||
|
static b32 pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn);
|
||||||
|
|
||||||
|
// ::MemAlloc::
|
||||||
|
|
||||||
|
static void * pMemAlloc(usize size);
|
||||||
|
static void * pMemAllocZeroed(usize size);
|
||||||
|
static void * pMemRealloc(void * ptr, usize old_size, usize new_size);
|
||||||
|
static void pMemFree(void * ptr, usize size);
|
||||||
|
|
||||||
|
// ::FileSystem::
|
||||||
|
|
||||||
|
static b32 pDirNavigate(char *dir);
|
||||||
|
static char **pDirGetFileNames(Arena *arena, u32 *count);
|
||||||
|
static pFile pFileOpen(char *file_name, pFileAccess access);
|
||||||
|
static void pFileClose(pFile file);
|
||||||
|
static u64 pFileRead(pFile file, u64 offset, void * buf, u64 len);
|
||||||
|
static u64 pFileWrite(pFile file, u64 offset, void * buf, u64 len);
|
||||||
|
static u64 pFileSeek(pFile file, u64 pos);
|
||||||
|
static u64 pFileLength(pFile file);
|
||||||
|
static b32 pFSIsVisible(char *name, b32 is_dir);
|
||||||
|
static b32 pDirIsVisible(char *dir_name);
|
||||||
|
static b32 pFileIsVisible(char *file_name);
|
||||||
|
static b32 pFileCanAccess(char *file_name, pFileAccess access);
|
||||||
|
|
||||||
|
// ::Profiling::
|
||||||
|
|
||||||
|
static u64 pOSTimerFreq();
|
||||||
|
static u64 pOSTimerRead();
|
||||||
|
static inline u64 pCPUTimerRead();
|
||||||
|
|
||||||
|
// ::Atomics::
|
||||||
|
|
||||||
|
static inline void pAtomicSignalFenceSeqCst();
|
||||||
|
static inline u32 pAtomicFetchSubU32(u32 volatile *ptr, u32 count);
|
||||||
|
static inline u32 pAtomicFetchIncrU32(u32 volatile *ptr);
|
||||||
|
static inline void pAtomicIncrU8(uint8_t volatile *ptr);
|
||||||
|
static inline void pAtomicIncrU32(u32 volatile *ptr);
|
||||||
|
static inline u32 pAtomicLoadU32(u32 volatile *ptr);
|
||||||
|
static inline void pAtomicStoreB32(b32 volatile *ptr, b32 value);
|
||||||
|
static inline b32 pAtomicCompareExchangeB32(b32 volatile *ptr, b32 *expect, b32 desired);
|
||||||
|
|
||||||
|
// ::Includes::
|
||||||
|
|
||||||
|
#include "util.cpp"
|
||||||
|
#include "alloc.cpp"
|
||||||
299
src/packer.cpp
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
// ::Packer::Includes::CFiles::Start::
|
||||||
|
|
||||||
|
#include "os.cpp"
|
||||||
|
|
||||||
|
#include "packer.h"
|
||||||
|
|
||||||
|
#include "assets.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ::Packer::Packing::Functions::Start::
|
||||||
|
|
||||||
|
i32
|
||||||
|
WriteHeader(pFile file, FileHeader *header)
|
||||||
|
{
|
||||||
|
i32 offset = 0;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MoveToShaderDir(c8 **return_dir)
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate("../assets/shaders") == 0, "Unable to change to shader directory");
|
||||||
|
*return_dir = "../../build";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MoveToTextureDir(c8 **return_dir)
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate("../assets/textures") == 0, "Unable to change to assets directory");
|
||||||
|
*return_dir = "../../build";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MoveToModelDir(c8 **return_dir)
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate("../assets/models") == 0, "Unable to change to assets directory");
|
||||||
|
*return_dir = "../../build";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InitHeader(FileHeader *header)
|
||||||
|
{
|
||||||
|
Assert(header != NULL, "File header is null");
|
||||||
|
|
||||||
|
header->magic_num = CreateMagicValue('s', 't', 'e', 'g');
|
||||||
|
header->version = FILE_VERSION;
|
||||||
|
|
||||||
|
header->asset_counts = SHADER_ASSET_MAX + TEXTURE_ASSET_MAX + MODEL_ASSET_MAX;
|
||||||
|
header->asset_offset = sizeof(FileHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackFiles(Arena *arena, FileHeader *header)
|
||||||
|
{
|
||||||
|
pFile file = pFileOpen("assets.sgp", pFS_WRITE | pFS_TRUNC | pFS_CREATE);
|
||||||
|
|
||||||
|
u64 file_pos = pFileWrite(file, 0, header, sizeof(FileHeader));
|
||||||
|
|
||||||
|
Assert(pDirNavigate("../assets") == 0, "Unable to move to assets directory");
|
||||||
|
|
||||||
|
u64 total_assets = SHADER_ASSET_MAX + TEXTURE_ASSET_MAX + MODEL_ASSET_MAX;
|
||||||
|
u64 asset_count = 0;
|
||||||
|
AssetFile *assets = MakeArray(arena, AssetFile, total_assets);
|
||||||
|
|
||||||
|
u64 data_offset = header->asset_offset + (sizeof(AssetFile) * total_assets);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < SHADER_ASSET_MAX; i++, asset_count++)
|
||||||
|
{
|
||||||
|
c8 *asset_name = g_Shader_Asset_Names[i];
|
||||||
|
|
||||||
|
Printfln("Packing file: %s at offset %llu...", asset_name, data_offset);
|
||||||
|
|
||||||
|
pFile asset_file = pFileOpen(asset_name, pFS_READ);
|
||||||
|
u64 file_size = pFileLength(asset_file);
|
||||||
|
|
||||||
|
u8 *file_data = MakeArray(arena, u8, file_size);
|
||||||
|
pFileRead(asset_file, 0, file_data, file_size);
|
||||||
|
|
||||||
|
u64 prev_offset = data_offset;
|
||||||
|
data_offset += pFileWrite(file, prev_offset, file_data, file_size);
|
||||||
|
|
||||||
|
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
|
||||||
|
|
||||||
|
assets[asset_count].data_offset = prev_offset;
|
||||||
|
assets[asset_count].len = file_size;
|
||||||
|
assets[asset_count].type = AT_SHADER;
|
||||||
|
assets[asset_count].hash = g_Shader_Asset_Hashes[i];
|
||||||
|
|
||||||
|
pFileClose(asset_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++, asset_count++)
|
||||||
|
{
|
||||||
|
c8 *asset_name = g_Texture_Asset_Names[i];
|
||||||
|
|
||||||
|
Printfln("Packing file: %s at offset %llu...", asset_name, data_offset);
|
||||||
|
|
||||||
|
pFile asset_file = pFileOpen(asset_name, pFS_READ);
|
||||||
|
u64 file_size = pFileLength(asset_file);
|
||||||
|
|
||||||
|
u8 *file_data = MakeArray(arena, u8, file_size);
|
||||||
|
pFileRead(asset_file, 0, file_data, file_size);
|
||||||
|
|
||||||
|
int ch = 4;
|
||||||
|
int w, h, has_ch;
|
||||||
|
u8 *image_bytes = stbi_load_from_memory(file_data, file_size, &w, &h, &has_ch, ch);
|
||||||
|
if (w <= 0 || h <= 0 || has_ch <= 0)
|
||||||
|
{
|
||||||
|
Printfln("%s", stbi_failure_reason());
|
||||||
|
Assert(0, "stbi_load_from_memory failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 loaded_length = u64(w * h * ch);
|
||||||
|
|
||||||
|
u64 prev_offset = data_offset;
|
||||||
|
data_offset += pFileWrite(file, data_offset, image_bytes, loaded_length);
|
||||||
|
|
||||||
|
Assert((data_offset - prev_offset) == loaded_length, "File write size invalid");
|
||||||
|
|
||||||
|
assets[asset_count].data_offset = prev_offset;
|
||||||
|
assets[asset_count].len = loaded_length;
|
||||||
|
assets[asset_count].type = AT_TEXTURE;
|
||||||
|
assets[asset_count].hash = g_Texture_Asset_Hashes[i];
|
||||||
|
assets[asset_count].texture_meta.w = u32(w);
|
||||||
|
assets[asset_count].texture_meta.h = u32(h);
|
||||||
|
assets[asset_count].texture_meta.ch = u32(ch);
|
||||||
|
|
||||||
|
stbi_image_free(image_bytes);
|
||||||
|
|
||||||
|
pFileClose(asset_file);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < MODEL_ASSET_MAX; i++, asset_count++)
|
||||||
|
{
|
||||||
|
c8 *asset_name = g_Model_Asset_Names[i];
|
||||||
|
|
||||||
|
Printfln("Packing file: %s at offset %llu...", asset_name, data_offset);
|
||||||
|
|
||||||
|
pFile asset_file = pFileOpen(asset_name, pFS_READ);
|
||||||
|
u64 file_size = pFileLength(asset_file);
|
||||||
|
|
||||||
|
u8 *file_data = MakeArray(arena, u8, file_size);
|
||||||
|
pFileRead(asset_file, 0, file_data, file_size);
|
||||||
|
|
||||||
|
u64 prev_offset = data_offset;
|
||||||
|
data_offset += pFileWrite(file, data_offset, file_data, file_size);
|
||||||
|
|
||||||
|
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
|
||||||
|
|
||||||
|
m3d_t *model = m3d_load(file_data, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
assets[asset_count].data_offset = prev_offset;
|
||||||
|
assets[asset_count].type = AT_MODEL;
|
||||||
|
assets[asset_count].len = file_size;
|
||||||
|
assets[asset_count].hash = g_Model_Asset_Hashes[i];
|
||||||
|
assets[asset_count].model_meta.i_count = u64(model->numface * 3);
|
||||||
|
|
||||||
|
m3d_free(model);
|
||||||
|
|
||||||
|
pFileClose(asset_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFileWrite(file, header->asset_offset, assets, sizeof(AssetFile)*asset_count);
|
||||||
|
|
||||||
|
pFileClose(file);
|
||||||
|
|
||||||
|
Assert(pDirNavigate("../build") == 0, "Unable to navigate back to build directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Packer::Packing::Functions::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Packer::Tests::Functions::Start::
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, pFile file)
|
||||||
|
{
|
||||||
|
pFile asset_file = pFileOpen(file_name, pFS_READ);
|
||||||
|
u64 size = pFileLength(asset_file);
|
||||||
|
|
||||||
|
u8 *file_data = MakeArray(arena, u8, size);
|
||||||
|
u64 write_count = pFileRead(asset_file, 0, file_data, size);
|
||||||
|
Assert(write_count == size, "Incorrect asset size retrieved");
|
||||||
|
|
||||||
|
u8 *packed_asset = MakeArray(arena, u8, file_info->len);
|
||||||
|
pFileRead(file, file_info->data_offset, packed_asset, file_info->len);
|
||||||
|
|
||||||
|
u8 *image_bytes;
|
||||||
|
u64 image_length;
|
||||||
|
if (file_info->type == TEXTURE_ASSET)
|
||||||
|
{
|
||||||
|
int ch = 4;
|
||||||
|
int w, h, has_ch;
|
||||||
|
image_bytes = stbi_load_from_memory(file_data, size, &w, &h, &has_ch, ch);
|
||||||
|
image_length = u64(w * h * ch);
|
||||||
|
|
||||||
|
Assert(file_info->len == image_length, "file length incorrect");
|
||||||
|
|
||||||
|
for (u64 i = 0; i < image_length; i++)
|
||||||
|
{
|
||||||
|
Assert(image_bytes[i] == packed_asset[i], "Asset file data is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_image_free(image_bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert(file_info->len == size, "file length incorrect");
|
||||||
|
|
||||||
|
for (u64 i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
Assert(file_data[i] == packed_asset[i], "Asset file data is invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFileClose(asset_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestAssetPack(Arena *arena)
|
||||||
|
{
|
||||||
|
pFile file = pFileOpen("assets.sgp", pFS_READ);
|
||||||
|
|
||||||
|
Assert(pDirNavigate("../assets") == 0, "Unable to navigate back to assets directory");
|
||||||
|
|
||||||
|
FileHeader header;
|
||||||
|
i64 offset = pFileRead(file, 0, &header, sizeof(FileHeader));
|
||||||
|
|
||||||
|
u64 asset_count = SHADER_ASSET_MAX + MODEL_ASSET_MAX + TEXTURE_ASSET_MAX;
|
||||||
|
|
||||||
|
Assert(header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic number is incorrect");
|
||||||
|
Assert(header.version == FILE_VERSION, "File version is incorrect");
|
||||||
|
|
||||||
|
Assert(header.asset_counts == asset_count, "Asset count incorrect");
|
||||||
|
|
||||||
|
AssetFile *files = MakeArray(arena, AssetFile, asset_count);
|
||||||
|
pFileRead(file, header.asset_offset, files, sizeof(AssetFile)*header.asset_counts);
|
||||||
|
|
||||||
|
u64 current_asset = 0;
|
||||||
|
for (u32 i = 0; i < SHADER_ASSET_MAX; i++, current_asset++)
|
||||||
|
{
|
||||||
|
TestAssetIsCorrect(arena, g_Shader_Asset_Names[i], files + current_asset, file);
|
||||||
|
Assert(files[current_asset].hash == g_Shader_Asset_Hashes[i], "Shader asset hash mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++, current_asset++)
|
||||||
|
{
|
||||||
|
TestAssetIsCorrect(arena, g_Texture_Asset_Names[i], files + current_asset, file);
|
||||||
|
Assert(files[current_asset].hash == g_Texture_Asset_Hashes[i], "Texture asset hash mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < MODEL_ASSET_MAX; i++, current_asset++)
|
||||||
|
{
|
||||||
|
TestAssetIsCorrect(arena, g_Model_Asset_Names[i], files + current_asset, file);
|
||||||
|
Assert(files[current_asset].hash == g_Model_Asset_Hashes[i], "Model asset hash mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Packer::Tests::Functions::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Packer::Main::Functions::Start::
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, c8 **argv)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
_set_fmode(_O_BINARY);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pDirIsVisible("build"))
|
||||||
|
{
|
||||||
|
Assert(pDirNavigate("./build") == 0, "Unable to change to build directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mem = pMemAllocZeroed(GB(1));
|
||||||
|
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
|
||||||
|
|
||||||
|
FileHeader header = {0};
|
||||||
|
InitHeader(&header);
|
||||||
|
|
||||||
|
PackFiles(arena, &header);
|
||||||
|
|
||||||
|
TestAssetPack(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Packer::Main::Functions::End::
|
||||||
41
src/packer.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ::Packer::Includes::Header::
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#include "assets.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// ::Packer::Macros::Header::
|
||||||
|
|
||||||
|
#define FWrite(buf, size, count, file) ((size) * (fwrite(buf, size, count, file)))
|
||||||
|
#define FRead(buf, size, count, file) ((size) * (fread(buf, size, count, file)))
|
||||||
|
|
||||||
|
// ::Packer::Types::Header::
|
||||||
|
|
||||||
|
typedef struct FileMapping
|
||||||
|
{
|
||||||
|
c8 *file_name;
|
||||||
|
u32 ix;
|
||||||
|
} FileMapping;
|
||||||
|
|
||||||
|
// ::Packer::Packing::Functions::Header::
|
||||||
|
|
||||||
|
void SetArrayLookups();
|
||||||
|
void InitHeader(FileHeader *header);
|
||||||
|
i32 WriteHeader(pFile file, FileHeader *header);
|
||||||
|
void PackFiles(Arena *arena, FileHeader *header);
|
||||||
|
void MoveToTextureDir(c8 **return_dir);
|
||||||
|
void MoveToShaderDir(c8 **return_dir);
|
||||||
|
void MoveToModelDir(c8 **return_dir);
|
||||||
|
|
||||||
|
// ::Packer::Tests::Functions::Header::
|
||||||
|
|
||||||
|
void TestAssetPack(Arena *arena);
|
||||||
|
static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *file_info, pFile file);
|
||||||
|
|
||||||
|
// ::Packer::Main::Functions::Header::
|
||||||
|
|
||||||
|
int main(int argc, char **argv);
|
||||||
268
src/renderer.cpp
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
#include "../external/glad/src/gl.c"
|
||||||
|
|
||||||
|
#include "assets.cpp"
|
||||||
|
|
||||||
|
// ::Globals::
|
||||||
|
|
||||||
|
PipelineCreateInfo g_Pipeline_Create_Info[] = {
|
||||||
|
{ .vertex_shader = "shaders/pbr.vert", .fragment_shader = "shaders/pbr.frag" },
|
||||||
|
//{ .vertex_shader = "shaders/gui.vert", .fragment_shader = "shaders/gui.frag" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// ::Init::Impl::Start::
|
||||||
|
|
||||||
|
MeshBuffer yoder;
|
||||||
|
|
||||||
|
static b32
|
||||||
|
Init(Renderer *renderer)
|
||||||
|
{
|
||||||
|
b32 success = true;
|
||||||
|
|
||||||
|
RGFW_setGLHint(RGFW_glMajor, 4);
|
||||||
|
RGFW_setGLHint(RGFW_glMinor, 6);
|
||||||
|
RGFW_setGLHint(RGFW_glProfile, RGFW_glCore);
|
||||||
|
|
||||||
|
renderer->window = RGFW_createWindow("Video Game", RGFW_RECT(0, 0, 1280, 720), RGFW_windowCenter | RGFW_windowNoResize);
|
||||||
|
if (renderer->window == NULL)
|
||||||
|
{
|
||||||
|
Printfln("Failed to create window");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
RGFW_window_makeCurrent(renderer->window);
|
||||||
|
|
||||||
|
int glad_version = gladLoaderLoadGL();
|
||||||
|
if (!glad_version)
|
||||||
|
{
|
||||||
|
Printfln("gladLoaderLoadGL failure");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < PIPELINE_MAX; i += 1)
|
||||||
|
{
|
||||||
|
renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
yoder = CreateMeshBuffer("models/yoda");
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PipelineHandle
|
||||||
|
BuildPipeline(PipelineCreateInfo *create_info)
|
||||||
|
{
|
||||||
|
auto vertex_shader = CreateShader(GL_VERTEX_SHADER);
|
||||||
|
Assert(BuildShader(&vertex_shader, create_info->vertex_shader), "BuildShader vertex failure");
|
||||||
|
|
||||||
|
auto fragment_shader = CreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
Assert(BuildShader(&fragment_shader, create_info->fragment_shader), "BuildShader fragment failure");
|
||||||
|
|
||||||
|
auto pipeline = CreatePipeline();
|
||||||
|
glAttachShader(pipeline, vertex_shader);
|
||||||
|
glAttachShader(pipeline, fragment_shader);
|
||||||
|
glLinkProgram(pipeline);
|
||||||
|
|
||||||
|
int success = 0;
|
||||||
|
glGetProgramiv(pipeline, GL_LINK_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
char info_log[512];
|
||||||
|
glGetProgramInfoLog(pipeline, 512, NULL, info_log);
|
||||||
|
Assert(false, "Failed to build pipeline");
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
BuildShader(ShaderHandle *handle, char *asset)
|
||||||
|
{
|
||||||
|
b32 success = true;
|
||||||
|
|
||||||
|
Asset data = apLoad(asset);
|
||||||
|
Assert(data.bytes != NULL && asset, "Shader data is NULL");
|
||||||
|
|
||||||
|
glShaderBinary(1, handle, GL_SHADER_BINARY_FORMAT_SPIR_V, data.bytes, data.len);
|
||||||
|
glSpecializeShader(*handle, "main", 0, 0, 0);
|
||||||
|
|
||||||
|
int compiled = 0;
|
||||||
|
glGetShaderiv(*handle, GL_COMPILE_STATUS, &compiled);
|
||||||
|
if (!compiled)
|
||||||
|
{
|
||||||
|
char info_log[512];
|
||||||
|
glGetShaderInfoLog(*handle, 512, NULL, info_log);
|
||||||
|
Printfln("Unable to compile shader: %s", info_log);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PipelineHandle
|
||||||
|
CreatePipeline()
|
||||||
|
{
|
||||||
|
PipelineHandle pipeline = glCreateProgram();
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VertexBuffer
|
||||||
|
CreateVertexBuffer()
|
||||||
|
{
|
||||||
|
VertexBuffer buf;
|
||||||
|
glGenBuffers(1, &buf);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IndexBuffer
|
||||||
|
CreateIndexBuffer()
|
||||||
|
{
|
||||||
|
IndexBuffer buf;
|
||||||
|
glGenBuffers(1, &buf);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VertexArray
|
||||||
|
CreateVertexArray()
|
||||||
|
{
|
||||||
|
VertexArray array;
|
||||||
|
glGenVertexArrays(1, &array);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ShaderHandle
|
||||||
|
CreateShader(int type)
|
||||||
|
{
|
||||||
|
return (ShaderHandle)glCreateShader(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MeshBuffer
|
||||||
|
CreateMeshBuffer(char *asset)
|
||||||
|
{
|
||||||
|
MeshBuffer mesh = {0};
|
||||||
|
|
||||||
|
/*
|
||||||
|
mesh.array = CreateVertexArray();
|
||||||
|
mesh.vertex = CreateVertexBuffer();
|
||||||
|
mesh.index = CreateIndexBuffer();
|
||||||
|
|
||||||
|
glBindVertexArray(mesh.array);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex);
|
||||||
|
|
||||||
|
Asset data = apLoad(asset);
|
||||||
|
Assert(data.model != NULL, "CreateMeshBuffer failed to load asset");
|
||||||
|
|
||||||
|
mesh.draw_count = data.model_meta.i_count;
|
||||||
|
|
||||||
|
Printfln("v_count: %llu", data.model->v_count);
|
||||||
|
|
||||||
|
glBufferData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
data.model->v_count * sizeof(Vertex),
|
||||||
|
data.model->vertices,
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index);
|
||||||
|
glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
data.model->i_count * sizeof(u32),
|
||||||
|
data.model->indices,
|
||||||
|
GL_STATIC_DRAW
|
||||||
|
);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, col));
|
||||||
|
|
||||||
|
apUnload(asset);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DrawMeshBuffer(MeshBuffer *mesh)
|
||||||
|
{
|
||||||
|
glBindVertexArray(mesh->array);
|
||||||
|
glDrawElements(GL_TRIANGLES, mesh->draw_count, GL_UNSIGNED_INT, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Init::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Textures::Impl::Start::
|
||||||
|
|
||||||
|
static u32
|
||||||
|
CreateTexture(rawptr data, u32 width, u32 height, u32 channels)
|
||||||
|
{
|
||||||
|
u32 tex;
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &tex);
|
||||||
|
|
||||||
|
i32 mipmap = Mini32(5, i32(log2f(f32(Maxi32(width, height)))));
|
||||||
|
|
||||||
|
u32 format, copy_format;
|
||||||
|
switch (channels)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
format = GL_R8;
|
||||||
|
copy_format = GL_RED;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
format = GL_RG8;
|
||||||
|
copy_format = GL_RG;
|
||||||
|
case 3:
|
||||||
|
format = GL_RGB8;
|
||||||
|
copy_format = GL_RGB;
|
||||||
|
case 4:
|
||||||
|
format = GL_RGBA8;
|
||||||
|
copy_format = GL_RGBA;
|
||||||
|
default:
|
||||||
|
Assert(false, "CreateTexture failure: unsupported channel number passed in");
|
||||||
|
}
|
||||||
|
|
||||||
|
glTextureStorage2D(tex, mipmap, format, width, height);
|
||||||
|
glTextureSubImage2D(tex, 0, 0, 0, width, height, copy_format, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTextureParameterf(tex, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glGenerateTextureMipmap(tex);
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Textures::Impl::End::
|
||||||
|
|
||||||
|
static b32
|
||||||
|
RunCycle(Renderer *renderer)
|
||||||
|
{
|
||||||
|
while (RGFW_window_checkEvent(renderer->window));
|
||||||
|
|
||||||
|
glUseProgram(renderer->pipelines[PIPELINE_PBR]);
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.8f, 0.4f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
DrawMeshBuffer(&yoder);
|
||||||
|
|
||||||
|
RGFW_window_swapBuffers(renderer->window);
|
||||||
|
|
||||||
|
return !RGFW_window_shouldClose(renderer->window);
|
||||||
|
}
|
||||||
63
src/renderer.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define RGFW_IMPLEMENTATION
|
||||||
|
#include "../external/rgfw/RGFW.h"
|
||||||
|
|
||||||
|
#include "assets.h"
|
||||||
|
|
||||||
|
typedef enum Pipeline_e
|
||||||
|
{
|
||||||
|
PIPELINE_PBR,
|
||||||
|
//PIPELINE_GUI,
|
||||||
|
PIPELINE_MAX,
|
||||||
|
} Pipeline;
|
||||||
|
|
||||||
|
typedef struct PipelineCreateInfo
|
||||||
|
{
|
||||||
|
char *vertex_shader;
|
||||||
|
char *fragment_shader;
|
||||||
|
} PipelineCreateInfo;
|
||||||
|
|
||||||
|
typedef unsigned int VertexBuffer;
|
||||||
|
typedef unsigned int IndexBuffer;
|
||||||
|
typedef unsigned int PipelineHandle;
|
||||||
|
typedef unsigned int ShaderHandle;
|
||||||
|
typedef unsigned int VertexArray;
|
||||||
|
typedef unsigned int UBO;
|
||||||
|
|
||||||
|
typedef struct MeshBuffer
|
||||||
|
{
|
||||||
|
VertexArray array;
|
||||||
|
VertexBuffer vertex;
|
||||||
|
IndexBuffer index;
|
||||||
|
u32 draw_count;
|
||||||
|
} MeshBuffer;
|
||||||
|
|
||||||
|
typedef struct Renderer
|
||||||
|
{
|
||||||
|
RGFW_window *window;
|
||||||
|
PipelineHandle pipelines[PIPELINE_MAX];
|
||||||
|
MeshBuffer models[MODEL_ASSET_MAX];
|
||||||
|
} Renderer;
|
||||||
|
|
||||||
|
// ::Init::Decl::
|
||||||
|
|
||||||
|
static b32 Init(Renderer *renderer);
|
||||||
|
static PipelineHandle CreatePipeline();
|
||||||
|
static VertexBuffer CreateVertexBuffer();
|
||||||
|
static IndexBuffer CreateIndexBuffer();
|
||||||
|
static VertexArray CreateVertexArray();
|
||||||
|
static ShaderHandle CreateShader(int type);
|
||||||
|
static PipelineHandle BuildPipeline(PipelineCreateInfo *create_info);
|
||||||
|
static MeshBuffer CreateMeshBuffer(char *asset);
|
||||||
|
static UBO CreateUBO(rawptr data, u32 size);
|
||||||
|
static b32 BuildShader(ShaderHandle *handle, char *asset);
|
||||||
|
|
||||||
|
// ::Textures::Decl::
|
||||||
|
|
||||||
|
static u32 CreateTexture(rawptr data, u32 width, u32 height);
|
||||||
|
|
||||||
|
// ::Draw::Decl::
|
||||||
|
|
||||||
|
static void DrawMeshBuffer(MeshBuffer *mesh);
|
||||||
|
|
||||||
10
src/shaders/pbr.frag.glsl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
layout (location = 0) in vec4 in_color;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = in_color;
|
||||||
|
}
|
||||||
12
src/shaders/pbr.vert.glsl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 in_pos;
|
||||||
|
layout (location = 1) in vec4 in_color;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(in_pos, 1.0);
|
||||||
|
out_color = in_color;
|
||||||
|
}
|
||||||
50
src/shaders/structures.glsl
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// ==========================================
|
||||||
|
// ====== TODO: Research values here ========
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
vec4 pos;
|
||||||
|
vec4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GUIVertex {
|
||||||
|
vec2 p0;
|
||||||
|
vec2 p1;
|
||||||
|
vec4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (buffer_reference, std430) readonly buffer VertexBuffer {
|
||||||
|
Vertex vertices[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (set = 0, binding = 0) uniform GlobalUniform {
|
||||||
|
vec2 res;
|
||||||
|
} Globals;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 1) uniform ShaderOptions {
|
||||||
|
float placeholder;
|
||||||
|
} Options;
|
||||||
|
|
||||||
|
layout (rgba16f, set = 0, binding = 2) uniform image2D image;
|
||||||
|
|
||||||
|
layout (set = 0, binding = 3) uniform sampler SamplerNearest;
|
||||||
|
|
||||||
|
layout (set = 1, binding = 0) uniform texture2D Textures[];
|
||||||
|
|
||||||
|
layout (set = 2, binding = 0) uniform PBRMaterials {
|
||||||
|
vec3 albedo;
|
||||||
|
vec3 normal;
|
||||||
|
float metallic;
|
||||||
|
float roughness;
|
||||||
|
float ao;
|
||||||
|
} Materials[];
|
||||||
|
|
||||||
|
layout (set = 3, binding = 0) uniform ModelMeshes {
|
||||||
|
VertexBuffer buf;
|
||||||
|
} Meshes[];
|
||||||
|
|
||||||
|
layout (push_constant) uniform Constants {
|
||||||
|
vec2 res;
|
||||||
|
float time;
|
||||||
|
uint mesh_index;
|
||||||
|
} PC;
|
||||||
284
src/util.cpp
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
// ::String8::Impl::Start::
|
||||||
|
|
||||||
|
static void
|
||||||
|
StrConcat(c8 *str, c8 *append)
|
||||||
|
{
|
||||||
|
u32 len = StrLen(str);
|
||||||
|
u32 i = 0;
|
||||||
|
for (; append[i] != '\0'; i += 1)
|
||||||
|
{
|
||||||
|
str[i] = append[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
str[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
StrEqL(const char *l, const char *r, u64 len)
|
||||||
|
{
|
||||||
|
for (u64 i = 0; *l == *r && *l && i < len; l++, r++, i++);
|
||||||
|
return *l == *r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
StrEq(const char *l, const char *r)
|
||||||
|
{
|
||||||
|
for (; *l == *r && *l; l++, r++);
|
||||||
|
return *l == '\0' && *r == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
StrLen(const char *str)
|
||||||
|
{
|
||||||
|
const char *start;
|
||||||
|
|
||||||
|
for (start = str; *str != '\0'; ++str)
|
||||||
|
/* Iterate only */;
|
||||||
|
|
||||||
|
return (u32)(str - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8
|
||||||
|
MakeString8(c8 *str, u64 len)
|
||||||
|
{
|
||||||
|
return (String8){ .value = str, .len = len };
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8
|
||||||
|
String8Concat(Arena *arena, String8 string, String8 append)
|
||||||
|
{
|
||||||
|
u64 str_len = string.len + append.len;
|
||||||
|
String8 str = {
|
||||||
|
.value = MakeArray(arena, c8, str_len + 1),
|
||||||
|
.len = str_len,
|
||||||
|
};
|
||||||
|
|
||||||
|
MemCpy(str.value, string.value, string.len);
|
||||||
|
MemCpy(str.value+string.len, append.value, append.len);
|
||||||
|
|
||||||
|
str.value[str_len] = '\0';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
String8TrimSuffix(String8 *str, c8 delimiter)
|
||||||
|
{
|
||||||
|
if (!str || str->len == 0) return;
|
||||||
|
|
||||||
|
for (i64 i = i64(str->len)-1; i > 0; i -= 1)
|
||||||
|
{
|
||||||
|
if (str->value[i] == delimiter)
|
||||||
|
{
|
||||||
|
str->value[i] = '\0';
|
||||||
|
str->len = i == 0 ? 0 : u64(i - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static i64
|
||||||
|
String8FindLast(String8 str, c8 delimiter)
|
||||||
|
{
|
||||||
|
if (str.len == 0) return -1;
|
||||||
|
|
||||||
|
i64 result = 1;
|
||||||
|
|
||||||
|
for (i64 i = i64(str.len)-1; i >= 0; i -= 1)
|
||||||
|
{
|
||||||
|
if (str.value[i] == delimiter)
|
||||||
|
{
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
String8Eq(String8 l, String8 r)
|
||||||
|
{
|
||||||
|
return StrEqL(l.value, r.value, l.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static b32
|
||||||
|
String8StartsWith(String8 string, String8 cmp)
|
||||||
|
{
|
||||||
|
return StrEqL(string.value, cmp.value, cmp.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8
|
||||||
|
PreSplitString8(String8 string, String8 delimiter)
|
||||||
|
{
|
||||||
|
if (string.len == 0 || delimiter.len == 0) return string;
|
||||||
|
|
||||||
|
u32 new_len = 0;
|
||||||
|
u32 matched_chars = 0;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < string.len; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (string.value[i] == delimiter.value[matched_chars])
|
||||||
|
matched_chars += 1;
|
||||||
|
else
|
||||||
|
matched_chars = 0;
|
||||||
|
|
||||||
|
if (matched_chars == delimiter.len || delimiter.value[matched_chars+1] == '\0')
|
||||||
|
{
|
||||||
|
new_len = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (String8){ .value = string.value, .len = new_len };
|
||||||
|
}
|
||||||
|
|
||||||
|
static String8
|
||||||
|
PreSplitNewString8(Arena *arena, String8 string, String8 delimiter)
|
||||||
|
{
|
||||||
|
String8 result = PreSplitString8(string, delimiter);
|
||||||
|
|
||||||
|
if (result.len > 0)
|
||||||
|
{
|
||||||
|
result.value = MakeArray(arena, char, result.len+1);
|
||||||
|
MemCpy(result.value, string.value, result.len);
|
||||||
|
result.value[result.len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::String8::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::Memory::Impl::Start::
|
||||||
|
|
||||||
|
static void
|
||||||
|
MemZero(void *ptr, isize size)
|
||||||
|
{
|
||||||
|
if (!size || !ptr) return;
|
||||||
|
|
||||||
|
isize iter_size = size > isizeof(u64) ? 8 : 1;
|
||||||
|
iter_size *= 4;
|
||||||
|
isize iter_len = size / iter_size;
|
||||||
|
|
||||||
|
u64 *mem = (u64 *)ptr;
|
||||||
|
|
||||||
|
if (iter_size > isizeof(u64))
|
||||||
|
{
|
||||||
|
while (iter_len > 0)
|
||||||
|
{
|
||||||
|
mem[0] = 0;
|
||||||
|
mem[1] = 0;
|
||||||
|
mem[2] = 0;
|
||||||
|
mem[3] = 0;
|
||||||
|
mem += 4;
|
||||||
|
iter_len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *byte_mem = (u8 *)mem;
|
||||||
|
isize rem_len = size % iter_size;
|
||||||
|
while (rem_len > 0)
|
||||||
|
{
|
||||||
|
byte_mem[0] = 0;
|
||||||
|
byte_mem++;
|
||||||
|
rem_len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
MemCpy(rawptr dst, rawptr src, usize size)
|
||||||
|
{
|
||||||
|
if (size == 0) return;
|
||||||
|
|
||||||
|
isize iter_size = size > isizeof(u64) ? 8 : 1;
|
||||||
|
iter_size *= 4;
|
||||||
|
isize iter_len = size / iter_size;
|
||||||
|
isize rem_len = 0;
|
||||||
|
|
||||||
|
u64 *mem_dst = (u64 *)dst;
|
||||||
|
u64 *mem_src = (u64 *)src;
|
||||||
|
|
||||||
|
|
||||||
|
if (iter_size > isizeof(size))
|
||||||
|
{
|
||||||
|
while (iter_len > 0)
|
||||||
|
{
|
||||||
|
mem_dst[0] = mem_src[0];
|
||||||
|
mem_dst[1] = mem_src[1];
|
||||||
|
mem_dst[2] = mem_src[2];
|
||||||
|
mem_dst[3] = mem_src[3];
|
||||||
|
mem_dst += 4;
|
||||||
|
mem_src += 4;
|
||||||
|
iter_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
rem_len = size % iter_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rem_len = size;
|
||||||
|
|
||||||
|
|
||||||
|
u8 *byte_dst = (u8 *)mem_dst;
|
||||||
|
u8 *byte_src = (u8 *)mem_src;
|
||||||
|
while (rem_len > 0)
|
||||||
|
{
|
||||||
|
byte_dst[0] = byte_src[0];
|
||||||
|
byte_dst++;
|
||||||
|
byte_src++;
|
||||||
|
rem_len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Memory::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Convert::Impl::Start::
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
U32ColToVec4(Vec4 *dst, u32 src)
|
||||||
|
{
|
||||||
|
if (src == 0)
|
||||||
|
{
|
||||||
|
dst->r = dst->g = dst->b = 0.0;
|
||||||
|
dst->a = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
U32ToVec4(dst, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
U32ToVec4(Vec4 *dst, u32 src)
|
||||||
|
{
|
||||||
|
dst->r = f32((src >> 0) & 0xFF) / 255.0;
|
||||||
|
dst->g = f32((src >> 8) & 0xFF) / 255.0;
|
||||||
|
dst->b = f32((src >> 16) & 0xFF) / 255.0;
|
||||||
|
dst->a = f32((src >> 24) & 0xFF) / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Convert::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ::Hashing::Impl::Start::
|
||||||
|
|
||||||
|
u64 static inline
|
||||||
|
HashFromString(String8 string)
|
||||||
|
{
|
||||||
|
return XXH3_64bits_withSeed(string.value, string.len, HASH_SEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Hashing::Impl::End::
|
||||||
|
|
||||||
|
|
||||||
|
// ::Math::Impl::Start::
|
||||||
|
|
||||||
|
DefMathImpl(Min);
|
||||||
|
DefMathImpl(Max);
|
||||||
|
|
||||||
|
// ::Math::Impl::End::
|
||||||
140
src/util.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// ::Constants::
|
||||||
|
|
||||||
|
constexpr usize DEFAULT_ALIGNMENT = (2*sizeof(rawptr));
|
||||||
|
constexpr u64 HASH_SEED = 5995;
|
||||||
|
|
||||||
|
// ::Macros::
|
||||||
|
|
||||||
|
#define Assert(condition, message) do { assert((condition) && (message)); } while(0)
|
||||||
|
|
||||||
|
#define KB(n) n * 1024LL
|
||||||
|
#define MB(n) KB(n) * 1024LL
|
||||||
|
#define GB(n) MB(n) * 1024LL
|
||||||
|
#define TB(n) GB(n) * 1024LL
|
||||||
|
|
||||||
|
#define BitEq(var, bits) (((var) & (bits)) == (bits))
|
||||||
|
#define AlignPow2(x, b) (((x) + (b) - 1) & (~((b) - 1)))
|
||||||
|
#define IsPow2(x) ((x) != 0 && ((x) &((x) - 1)) == 0)
|
||||||
|
#define PtrAdd(ptr, add) ((rawptr)(((uintptr)ptr) + ((uintptr)add)))
|
||||||
|
|
||||||
|
#define MakeArray(arena, type, count) (type *)(ArenaAlloc(arena, (isize)(sizeof(type)) * (isize)(count)))
|
||||||
|
#define Len(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||||
|
|
||||||
|
#define i8(x) ((i8)(x))
|
||||||
|
#define i16(x) ((i16)(x))
|
||||||
|
#define i32(x) ((i32)(x))
|
||||||
|
#define i64(x) ((i64)(x))
|
||||||
|
|
||||||
|
#define u8(x) ((u8)(x))
|
||||||
|
#define u16(x) ((u16)(x))
|
||||||
|
#define u32(x) ((u32)(x))
|
||||||
|
#define u64(x) ((u64)(x))
|
||||||
|
|
||||||
|
#define c8(x) ((c8)(x))
|
||||||
|
#define c8ptr(x) ((c8 *)(x))
|
||||||
|
#define u8ptr(x) ((u8 *)(x))
|
||||||
|
#define i8ptr(x) ((i8 *)(x))
|
||||||
|
|
||||||
|
#define intptr(x) ((intptr)(x))
|
||||||
|
#define uintptr(x) ((uintptr)(x))
|
||||||
|
|
||||||
|
#define f32(x) ((f32)(x))
|
||||||
|
#define f64(x) ((f64)(x))
|
||||||
|
|
||||||
|
#define rawptr(x) ((rawptr)(x))
|
||||||
|
|
||||||
|
#define String8Array(v, c) MakeString8((c8 *)(v), sizeof(*(v))*(c))
|
||||||
|
#define String8Struct(v) MakeString8((c8 *)(v), sizeof(*(v)))
|
||||||
|
#define String8CStr(v) MakeString8((c8 *)v, StrLen(v))
|
||||||
|
|
||||||
|
#define DefIntegerImpl(def) \
|
||||||
|
Def##def(i8); \
|
||||||
|
Def##def(i16); \
|
||||||
|
Def##def(i32); \
|
||||||
|
Def##def(i64); \
|
||||||
|
Def##def(u8); \
|
||||||
|
Def##def(u16); \
|
||||||
|
Def##def(u32); \
|
||||||
|
Def##def(u64)
|
||||||
|
|
||||||
|
#define DefFloatImpl(def) \
|
||||||
|
Def##def(f32); \
|
||||||
|
Def##def(f64)
|
||||||
|
|
||||||
|
#define DefMathImpl(def) \
|
||||||
|
DefIntegerImpl(def); \
|
||||||
|
DefFloatImpl(def)
|
||||||
|
|
||||||
|
#define ArrayType(T) \
|
||||||
|
typedef struct T##Array \
|
||||||
|
{ \
|
||||||
|
T *data; \
|
||||||
|
u64 length; \
|
||||||
|
} T##Array
|
||||||
|
|
||||||
|
#define PtrArrayType(T) \
|
||||||
|
typedef struct T##PtrArray \
|
||||||
|
{ \
|
||||||
|
T **data; \
|
||||||
|
u64 length; \
|
||||||
|
} T##PtrArray
|
||||||
|
|
||||||
|
#define InitArrayType(arr, arena, T, len) \
|
||||||
|
arr.data = MakeArray(arena, T, len); \
|
||||||
|
arr.length = len
|
||||||
|
|
||||||
|
// ::String8::
|
||||||
|
|
||||||
|
static b32 String8Eq(String8 l, String8 r);
|
||||||
|
static u32 StrLen(const char *str);
|
||||||
|
static b32 StrEqL(const char *l, const char *r, u64 len);
|
||||||
|
static b32 StrEq(const char *l, const char *r);
|
||||||
|
static void StrConcat(c8 *str, c8 *append);
|
||||||
|
static String8 MakeString8(c8 *str, u64 len);
|
||||||
|
static String8 String8Concat(Arena *arena, String8 string, String8 append);
|
||||||
|
static void String8TrimSuffix(String8 *str, c8 delimiter);
|
||||||
|
static i64 String8FindLast(String8 str, c8 delimiter);
|
||||||
|
static String8 PreSplitString8(String8 string, String8 delimiter);
|
||||||
|
static String8 PreSplitNewString8(Arena *arena, String8 string, String8 delimiter);
|
||||||
|
|
||||||
|
// ::Memory::
|
||||||
|
|
||||||
|
static void MemZero(void *ptr, isize size);
|
||||||
|
static void MemCpy(rawptr dst, rawptr src, usize len);
|
||||||
|
|
||||||
|
// ::Convert::
|
||||||
|
|
||||||
|
static inline void U32ColToVec4(Vec4 *dst, u32 src);
|
||||||
|
static inline void U32ToVec4(Vec4 *dst, u32 src);
|
||||||
|
|
||||||
|
// ::Math::
|
||||||
|
|
||||||
|
#define DefMin(T) \
|
||||||
|
T Min##T(T l, T r) \
|
||||||
|
{ \
|
||||||
|
return l < r ? l : r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DefMax(T) \
|
||||||
|
T Max##T(T l, T r) \
|
||||||
|
{ \
|
||||||
|
return l > r ? l : r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DefClamp(T) \
|
||||||
|
T Clamp##T(T v, T min, T max) \
|
||||||
|
{ \
|
||||||
|
return Min##T(max, Max##T(v, min)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DefAbs(T) \
|
||||||
|
T Abs##T(T v) \
|
||||||
|
{ \
|
||||||
|
return v < (T)0 ? -v : v; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// ::Hashing::
|
||||||
|
|
||||||
|
u64 static inline HashFromString(String8 string);
|
||||||