mirror of
https://github.com/raysan5/raylib.git
synced 2026-05-26 14:40:27 -04:00
Compare commits
45 Commits
cf9f27db54
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f9ded7642 | |||
| 34b06ca587 | |||
| 4d845608b8 | |||
| eaf32c83bf | |||
| 808e6b9b20 | |||
| 7dd72e7328 | |||
| f8270483e1 | |||
| f17babfe8a | |||
| f65d5ad7a9 | |||
| 0d78f10161 | |||
| 7d5b61ce01 | |||
| b48933b096 | |||
| fd1dfd7d65 | |||
| be56f2c524 | |||
| d31c10a01e | |||
| c04e57399a | |||
| 6c090f6193 | |||
| 5ca45bce37 | |||
| 729327a078 | |||
| ea76845ecb | |||
| 5506aed190 | |||
| 43366d1c6a | |||
| f35f4b9fad | |||
| c4b4fcc17e | |||
| fbf132d1d1 | |||
| e274c195af | |||
| fd28dc5644 | |||
| 5aa3de194c | |||
| 9400199b80 | |||
| 200d344dee | |||
| 094edcd32e | |||
| a005a044da | |||
| ae315eecb9 | |||
| dcb0ca5d14 | |||
| 07b729d5d6 | |||
| cd4599b447 | |||
| b2ea5eae5e | |||
| 29ff1f02e9 | |||
| d840a100a7 | |||
| 95bfa196fd | |||
| aceb8ce3a8 | |||
| 33e889907e | |||
| 61537200c0 | |||
| 080f5c94bd | |||
| 7207c03c72 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -65,7 +65,7 @@ src/external/SDL3
|
||||
# Emscripten
|
||||
emsdk
|
||||
|
||||
# Ignore wasm data in examples/
|
||||
# Ignore binaries generated in examples/
|
||||
examples/**/*
|
||||
!examples/**/*.*
|
||||
!examples/**/*/
|
||||
|
||||
@ -11,7 +11,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
|
||||
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
|
||||
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
|
||||
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **6.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
|
||||
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
|
||||
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
|
||||
@ -37,7 +37,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
||||
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
||||
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
|
||||
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
|
||||
| [raylib-go](https://github.com/gen2brain/raylib-go) | **6.0** | [Go](https://golang.org) | Zlib |
|
||||
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
|
||||
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
|
||||
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
|
||||
@ -49,7 +49,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
|
||||
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
|
||||
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
|
||||
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC |
|
||||
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||
| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
|
||||
@ -90,7 +90,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
|
||||
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
|
||||
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
|
||||
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **6.0** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
|
||||
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
|
||||
@ -106,6 +106,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
|
||||
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
|
||||
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
|
||||
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
|
||||
| [gclang-raylib](https://github.com/gnuchanos/gcLang_Compiler/tree/main/windows_version/raylib_version)| **6.0** | [gclang](https://github.com/gnuchanos/gcLang_Compiler) | AGPL-3.0 |
|
||||
|
||||
|
||||
### Utility Wrapers
|
||||
|
||||
@ -29,7 +29,7 @@ include(CompilerFlags)
|
||||
# Registers build options that are exposed to cmake
|
||||
include(CMakeOptions.txt)
|
||||
|
||||
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web")
|
||||
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web" AND NOT "${PLATFORM}" MATCHES "SDL")
|
||||
if (NOT GLFW_BUILD_WAYLAND AND NOT GLFW_BUILD_X11)
|
||||
message(FATAL_ERROR "Cannot disable both Wayland and X11")
|
||||
endif()
|
||||
|
||||
@ -6,7 +6,7 @@ if(EMSCRIPTEN)
|
||||
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
|
||||
SET(PLATFORM Web CACHE STRING "Platform to build for.")
|
||||
endif()
|
||||
enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
|
||||
enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
|
||||
|
||||
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
|
||||
|
||||
@ -29,11 +29,15 @@ option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF)
|
||||
option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON)
|
||||
|
||||
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF)
|
||||
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
|
||||
|
||||
include(ParseConfigHeader)
|
||||
|
||||
foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS)
|
||||
string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG})
|
||||
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CMAKE_MATCH_2} CUSTOMIZE_BUILD ${CMAKE_MATCH_2})
|
||||
set(CONFIG_HEADER_FLAG_DEFAULT ${CMAKE_MATCH_2})
|
||||
if (INCLUDE_EVERYTHING AND "${CONFIG_HEADER_FLAG_DEFAULT}" STREQUAL "OFF")
|
||||
set(CONFIG_HEADER_FLAG_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CONFIG_HEADER_FLAG_DEFAULT} CUSTOMIZE_BUILD ${CONFIG_HEADER_FLAG_DEFAULT})
|
||||
endforeach()
|
||||
|
||||
@ -739,7 +739,6 @@ fn addExamples(
|
||||
.root_module = exe_mod,
|
||||
.use_lld = target.result.os.tag == .windows,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
|
||||
|
||||
|
||||
@ -7,6 +7,30 @@ if(POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
function(raylib_check_libatomic_required result)
|
||||
set(_atomic_test_source "
|
||||
int main(void)
|
||||
{
|
||||
volatile long long value = 0;
|
||||
return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST);
|
||||
}")
|
||||
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
|
||||
if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
set(${result} FALSE PARENT_SCOPE)
|
||||
else ()
|
||||
cmake_push_check_state()
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC)
|
||||
cmake_pop_check_state()
|
||||
set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
|
||||
|
||||
if (${PLATFORM} STREQUAL "Desktop")
|
||||
@ -67,6 +91,21 @@ if (${PLATFORM} STREQUAL "Desktop")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
elseif (${PLATFORM} STREQUAL "Win32")
|
||||
if ((NOT WIN32) AND (NOT CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64"))
|
||||
message(FATAL_ERROR "Win32 platform requires Windows or a cross compiler.")
|
||||
endif ()
|
||||
|
||||
set(PLATFORM_CPP "PLATFORM_DESKTOP_WIN32")
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (${OPENGL_VERSION} MATCHES "Software")
|
||||
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
|
||||
endif ()
|
||||
|
||||
find_package(OpenGL QUIET)
|
||||
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
|
||||
|
||||
elseif (${PLATFORM} STREQUAL "Web")
|
||||
set(PLATFORM_CPP "PLATFORM_WEB")
|
||||
if(NOT GRAPHICS)
|
||||
@ -222,6 +261,14 @@ endif ()
|
||||
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
|
||||
|
||||
if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE)
|
||||
raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED)
|
||||
if (RAYLIB_LIBATOMIC_REQUIRED)
|
||||
message(STATUS "64-bit atomics require libatomic")
|
||||
list(APPEND LIBS_PRIVATE atomic)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (${PLATFORM} MATCHES "Desktop")
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
|
||||
endif ()
|
||||
|
||||
@ -10,7 +10,9 @@ string(REGEX MATCHALL ${MACRO_REGEX} MACRO_LIST ${CONFIG_HEADER_CONTENT})
|
||||
set(CONFIG_HEADER_FLAGS ${MACRO_LIST})
|
||||
list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=ON]])
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=\3]] REGEX "^[^/]")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=0$]] [[=OFF]])
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=1$]] [[=ON]])
|
||||
|
||||
set(CONFIG_HEADER_VALUES ${MACRO_LIST})
|
||||
list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)")
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
# - Linux (X11 desktop mode)
|
||||
# - macOS/OSX (x64, arm64 (not tested))
|
||||
# - Others (not tested)
|
||||
# > PLATFORM_DESKTOP_WIN32 (native Win32):
|
||||
# - Windows (Win32, Win64)
|
||||
# > PLATFORM_WEB_RGFW:
|
||||
# - HTML5 (WebAssembly)
|
||||
# > PLATFORM_WEB:
|
||||
@ -794,6 +796,23 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
rm -f *.o
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
del *.o *.exe /s
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
find . -type f -perm -ugo+x -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
find . -type f -executable -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
find . -type f -perm +ugo+x -delete
|
||||
rm -f *.o
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
find . -type f -executable -delete
|
||||
rm -fv *.o
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) || defined(PLATFORM_DESKTOP_RGFW)
|
||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#include "glad_gles2.h" // Required for: OpenGL functionality
|
||||
#define glGenVertexArrays glGenVertexArraysOES
|
||||
|
||||
@ -240,6 +240,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||
ifeq ($(ANDROID_ARCH),x86_64)
|
||||
ANDROID_COMPILER_ARCH = x86_64
|
||||
endif
|
||||
ifndef ANDROID_COMPILER_ARCH
|
||||
$(error ANDROID_COMPILER_ARCH: Unknown ANDROID_ARCH=$(ANDROID_ARCH))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Define raylib graphics api depending on selected platform
|
||||
|
||||
4
src/external/jar_mod.h
vendored
4
src/external/jar_mod.h
vendored
@ -1538,10 +1538,10 @@ mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename)
|
||||
modctx->modfile = (muchar *) JARMOD_MALLOC(fsize);
|
||||
modctx->modfilesize = fsize;
|
||||
memset(modctx->modfile, 0, fsize);
|
||||
fread(modctx->modfile, fsize, 1, f);
|
||||
if(fread(modctx->modfile, fsize, 1, f) != 1) fsize = 0;
|
||||
fclose(f);
|
||||
|
||||
if(!jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0;
|
||||
if(fsize && !jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0;
|
||||
} else fsize = 0;
|
||||
}
|
||||
return fsize;
|
||||
|
||||
4
src/external/miniaudio.h
vendored
4
src/external/miniaudio.h
vendored
@ -41495,11 +41495,11 @@ Web Audio Backend
|
||||
#ifdef MA_HAS_WEBAUDIO
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
#if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 32)))
|
||||
#if (__EMSCRIPTEN_MAJOR__ > 3) || (__EMSCRIPTEN_MAJOR__ == 3 && (__EMSCRIPTEN_MINOR__ > 1 || (__EMSCRIPTEN_MINOR__ == 1 && __EMSCRIPTEN_TINY__ >= 32)))
|
||||
#include <emscripten/webaudio.h>
|
||||
#define MA_SUPPORT_AUDIO_WORKLETS
|
||||
|
||||
#if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 70)))
|
||||
#if (__EMSCRIPTEN_MAJOR__ > 3) || (__EMSCRIPTEN_MAJOR__ == 3 && (__EMSCRIPTEN_MINOR__ > 1 || (__EMSCRIPTEN_MINOR__ == 1 && __EMSCRIPTEN_TINY__ >= 70)))
|
||||
#define MA_SUPPORT_AUDIO_WORKLETS_VARIABLE_BUFFER_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
262
src/external/rlsw.h
vendored
262
src/external/rlsw.h
vendored
@ -164,6 +164,18 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Fast power-of-two texture wrap (SW_REPEAT mode only)
|
||||
// When defined, textures whose width/height are powers of two use a bitmask
|
||||
// wrap (`x & (size-1)`) instead of `floorf`-based fractional wrap or the signed `%` chain in the linear sampler
|
||||
// Saves a software divide on Xtensa and a few instructions everywhere
|
||||
// NPOT textures keep using the original path via a runtime `(size & (size-1)) == 0` check,
|
||||
// so SW_REPEAT remains correct for them
|
||||
// The only observable behavior change is for POT textures sampled with negative UV coordinates:
|
||||
// bitmask wrap (two's complement) can differ from `sw_fract` by one texel
|
||||
// Off by default to keep bit-for-bit behavior; opt in if you control your asset UVs
|
||||
//
|
||||
//#define SW_TEXTURE_REPEAT_POT_FAST
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// OpenGL Compatibility Types
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -200,6 +212,7 @@ typedef double GLclampd;
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
|
||||
//#define GL_ATTRIB_STACK_DEPTH 0x0BB0
|
||||
//#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
|
||||
@ -507,6 +520,7 @@ typedef enum {
|
||||
SW_RENDERER = GL_RENDERER,
|
||||
SW_VERSION = GL_VERSION,
|
||||
SW_EXTENSIONS = GL_EXTENSIONS,
|
||||
SW_SHADING_LANGUAGE_VERSION = GL_SHADING_LANGUAGE_VERSION,
|
||||
SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE,
|
||||
SW_DEPTH_CLEAR_VALUE = GL_DEPTH_CLEAR_VALUE,
|
||||
SW_CURRENT_COLOR = GL_CURRENT_COLOR,
|
||||
@ -844,6 +858,15 @@ SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWatta
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ESP-DSP acceleration: ESP-IDF ships an optimized math library that includes
|
||||
// `dspm_mult_4x4x4_f32` (4x4 matrix multiply) and `dspm_mult_4x4x1_f32` (matrix * vector)
|
||||
// These are S3-tuned hand-vectorized kernels that beat the scalar versions for both throughput and code-size
|
||||
// Detection is opt-in to keep the dependency optional: define SW_USE_ESP_DSP from your build system
|
||||
#if defined(ESP_PLATFORM) && defined(SW_USE_ESP_DSP)
|
||||
#define SW_HAS_ESP_DSP
|
||||
#include "dspm_mult.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define SW_CURLY_INIT(name) name
|
||||
#else
|
||||
@ -858,10 +881,10 @@ SWAPI void swGetFramebufferAttachmentParameteriv(SWattachment attachment, SWatta
|
||||
#define SW_DEG2RAD (SW_PI/180.0f)
|
||||
#define SW_RAD2DEG (180.0f/SW_PI)
|
||||
|
||||
// When clipping a convex polygon against a plane, at most one vertex is added.
|
||||
// When clipping a convex polygon against a plane, at most one vertex is added
|
||||
// Starting from a quadrilateral (4 vertices), clipped sequentially against
|
||||
// the frustum (6 planes) then the scissor rectangle (4 planes):
|
||||
// 4 + 6 + 4 = 14 vertices maximum.
|
||||
// 4 + 6 + 4 = 14 vertices maximum
|
||||
#define SW_MAX_CLIPPED_POLYGON_VERTICES 14
|
||||
#define SW_CLIP_EPSILON 1e-4f
|
||||
|
||||
@ -1038,6 +1061,9 @@ typedef struct {
|
||||
SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION)
|
||||
sw_matrix_t *currentMatrix; // Pointer to the currently used matrix according to the mode
|
||||
sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally
|
||||
#ifdef SW_HAS_ESP_DSP
|
||||
float matMVP_rm[16]; // Row-major MVP, kept in sync for esp-dsp dspm_mult_4x4x1_f32 vertex transform
|
||||
#endif
|
||||
bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt
|
||||
|
||||
sw_handle_t boundFramebufferId; // Framebuffer currently bound
|
||||
@ -1141,6 +1167,14 @@ static inline void sw_matrix_id(sw_matrix_t dst)
|
||||
|
||||
static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RESTRICT left, const float *SW_RESTRICT right)
|
||||
{
|
||||
#ifdef SW_HAS_ESP_DSP
|
||||
// dspm_mult_4x4x4_f32 treats its operands as row-major. rlsw stores matrices
|
||||
// column-major, so passing them flat is equivalent to passing transposes:
|
||||
// dspm_mult(L^T, R^T) computes (L^T)*(R^T) = (R*L)^T, written back into a
|
||||
// flat array gives the same bit pattern as the column-major product (R*L)
|
||||
// -- exactly the semantic the scalar fallback below has
|
||||
dspm_mult_4x4x4_f32(left, right, dst);
|
||||
#else
|
||||
float l00 = left[0], l01 = left[1], l02 = left[2], l03 = left[3];
|
||||
float l10 = left[4], l11 = left[5], l12 = left[6], l13 = left[7];
|
||||
float l20 = left[8], l21 = left[9], l22 = left[10], l23 = left[11];
|
||||
@ -1165,6 +1199,7 @@ static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RES
|
||||
dst[7] = l10*right[3] + l11*right[7] + l12*right[11] + l13*right[15];
|
||||
dst[11] = l20*right[3] + l21*right[7] + l22*right[11] + l23*right[15];
|
||||
dst[15] = l30*right[3] + l31*right[7] + l32*right[11] + l33*right[15];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right)
|
||||
@ -1210,6 +1245,33 @@ static inline float sw_fract(float x)
|
||||
return (x - floorf(x));
|
||||
}
|
||||
|
||||
// Xtensa architecture optimization
|
||||
// Fast reciprocal: 1-ULP accurate in ~7 instructions using the
|
||||
// hardware `recip0.s` seed + two Newton-Raphson refinement steps
|
||||
// All work stays in FPU registers — no `__divsf3` software call
|
||||
// Hot-path divisions in the rasterizer (span/triangle setup, perspective divide, etc.) call this
|
||||
// On non-Xtensa targets it transparently expands to `1.0f / x`, so generated code is identical to before
|
||||
#if defined(__XTENSA__)
|
||||
__attribute__((always_inline))
|
||||
static inline float sw_rcp(float x)
|
||||
{
|
||||
float result, temp;
|
||||
__asm__(
|
||||
"recip0.s %0, %2\n"
|
||||
"const.s %1, 1\n"
|
||||
"msub.s %1, %2, %0\n"
|
||||
"madd.s %0, %0, %1\n"
|
||||
"const.s %1, 1\n"
|
||||
"msub.s %1, %2, %0\n"
|
||||
"maddn.s %0, %0, %1\n"
|
||||
: "=&f"(result), "=&f"(temp) : "f"(x)
|
||||
);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static inline float sw_rcp(float x) { return 1.0f/x; }
|
||||
#endif
|
||||
|
||||
static inline uint8_t sw_luminance8(const uint8_t *color)
|
||||
{
|
||||
return (uint8_t)((color[0]*77 + color[1]*150 + color[2]*29) >> 8);
|
||||
@ -2406,11 +2468,31 @@ static inline void sw_texture_free(sw_texture_t *texture)
|
||||
|
||||
static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
|
||||
{
|
||||
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
|
||||
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
|
||||
int x, y;
|
||||
|
||||
int x = u*tex->width;
|
||||
int y = v*tex->height;
|
||||
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||
if ((tex->sWrap == SW_REPEAT) && ((tex->width & tex->wMinus1) == 0))
|
||||
{
|
||||
x = (int)(u*tex->width) & tex->wMinus1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
|
||||
x = (int)(u*tex->width);
|
||||
}
|
||||
|
||||
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||
if ((tex->tWrap == SW_REPEAT) && ((tex->height & tex->hMinus1) == 0))
|
||||
{
|
||||
y = (int)(v*tex->height) & tex->hMinus1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
|
||||
y = (int)(v*tex->height);
|
||||
}
|
||||
|
||||
tex->readColor(color, tex->pixels, y*tex->width + x);
|
||||
}
|
||||
@ -2432,13 +2514,19 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t
|
||||
int x1 = x0 + 1;
|
||||
int y1 = y0 + 1;
|
||||
|
||||
// NOTE: If the textures are POT, avoid the division for SW_REPEAT
|
||||
|
||||
if (tex->sWrap == SW_CLAMP)
|
||||
{
|
||||
x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0;
|
||||
x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1;
|
||||
}
|
||||
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||
else if ((tex->width & tex->wMinus1) == 0)
|
||||
{
|
||||
// POT fast path: bitmask wrap covers negative ints via two's complement
|
||||
x0 = x0 & tex->wMinus1;
|
||||
x1 = x1 & tex->wMinus1;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
x0 = (x0%tex->width + tex->width)%tex->width;
|
||||
@ -2450,6 +2538,13 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t
|
||||
y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0;
|
||||
y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1;
|
||||
}
|
||||
#ifdef SW_TEXTURE_REPEAT_POT_FAST
|
||||
else if ((tex->height & tex->hMinus1) == 0)
|
||||
{
|
||||
y0 = y0 & tex->hMinus1;
|
||||
y1 = y1 & tex->hMinus1;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
y0 = (y0%tex->height + tex->height)%tex->height;
|
||||
@ -3366,7 +3461,7 @@ static void sw_triangle_clip_and_project(void)
|
||||
|
||||
// Calculation of the reciprocal of W for normalization
|
||||
// as well as perspective-correct attributes
|
||||
const float wRcp = 1.0f/v->position[3];
|
||||
const float wRcp = sw_rcp(v->position[3]);
|
||||
|
||||
// Division of XYZ coordinates by weight
|
||||
v->position[0] *= wRcp;
|
||||
@ -3460,8 +3555,8 @@ static inline bool sw_quad_face_culling(void)
|
||||
// winding in the projected space when all w > 0
|
||||
// A value of 0 for sgnArea means P0, P1, P2 are collinear in (x, y, w)
|
||||
// space, which corresponds to a degenerate triangle projection
|
||||
// Such quads might also be degenerate or non-planar. They are typically
|
||||
// not culled by this test (0 < 0 is false, 0 > 0 is false)
|
||||
// Such quads might also be degenerate or non-planar
|
||||
// They are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
|
||||
// and should be handled by the clipper if necessary
|
||||
|
||||
return (RLSW.cullFace == SW_FRONT)? (sgnArea < 0.0f) : (sgnArea > 0.0f); // Cull if winding is "clockwise" : "counter-clockwise"
|
||||
@ -3481,7 +3576,7 @@ static void sw_quad_clip_and_project(void)
|
||||
|
||||
// Calculation of the reciprocal of W for normalization
|
||||
// as well as perspective-correct attributes
|
||||
const float wRcp = 1.0f/v->position[3];
|
||||
const float wRcp = sw_rcp(v->position[3]);
|
||||
|
||||
// Division of XYZ coordinates by weight
|
||||
v->position[0] *= wRcp;
|
||||
@ -3659,8 +3754,8 @@ static bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1)
|
||||
if (!sw_line_clip(v0, v1)) return false;
|
||||
|
||||
// Convert clip coordinates to NDC
|
||||
v0->position[3] = 1.0f/v0->position[3];
|
||||
v1->position[3] = 1.0f/v1->position[3];
|
||||
v0->position[3] = sw_rcp(v0->position[3]);
|
||||
v1->position[3] = sw_rcp(v1->position[3]);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
v0->position[i] *= v0->position[3];
|
||||
@ -3709,7 +3804,7 @@ static bool sw_point_clip_and_project(sw_vertex_t *v)
|
||||
if ((v->position[i] < -v->position[3]) || (v->position[i] > v->position[3])) return false;
|
||||
}
|
||||
|
||||
v->position[3] = 1.0f/v->position[3];
|
||||
v->position[3] = sw_rcp(v->position[3]);
|
||||
v->position[0] *= v->position[3];
|
||||
v->position[1] *= v->position[3];
|
||||
v->position[2] *= v->position[3];
|
||||
@ -3781,8 +3876,7 @@ static inline void sw_poly_fill_render(uint32_t state)
|
||||
//-------------------------------------------------------------------------------------------
|
||||
static void sw_immediate_begin(SWdraw mode)
|
||||
{
|
||||
// NOTE: Any checks to ensure command recording can start
|
||||
// must be performed before calling this function.
|
||||
// NOTE: Any checks to ensure command recording can start must be performed before calling this function
|
||||
|
||||
// Recalculate the MVP if this is needed
|
||||
if (RLSW.isDirtyMVP)
|
||||
@ -3791,6 +3885,19 @@ static void sw_immediate_begin(SWdraw mode)
|
||||
RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
|
||||
RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
|
||||
|
||||
#ifdef SW_HAS_ESP_DSP
|
||||
// Pre-transpose to row-major so dspm_mult_4x4x1_f32(matMVP_rm, v, out)
|
||||
// computes M*v directly in the per-vertex hot path; 16 scalar copies
|
||||
// per MVP update vs saving ~20 cycles per vertex transform
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
RLSW.matMVP_rm[4*i + j] = RLSW.matMVP[4*j + i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RLSW.isDirtyMVP = false;
|
||||
}
|
||||
|
||||
@ -3842,11 +3949,17 @@ static void sw_immediate_push_vertex(const float position[4])
|
||||
sw_vertex_t *vertex = &RLSW.primitive.buffer[RLSW.primitive.vertexCount++];
|
||||
|
||||
// Calculate clip coordinates
|
||||
#ifdef SW_HAS_ESP_DSP
|
||||
// dspm_mult_4x4x1_f32 declares its inputs non-const; rlsw treats them as
|
||||
// read-only and the cast is safe (the kernel only loads from B)
|
||||
dspm_mult_4x4x1_f32(RLSW.matMVP_rm, (float *)position, vertex->position);
|
||||
#else
|
||||
const float *m = RLSW.matMVP;
|
||||
vertex->position[0] = m[0]*position[0] + m[4]*position[1] + m[8]*position[2] + m[12]*position[3];
|
||||
vertex->position[1] = m[1]*position[0] + m[5]*position[1] + m[9]*position[2] + m[13]*position[3];
|
||||
vertex->position[2] = m[2]*position[0] + m[6]*position[1] + m[10]*position[2] + m[14]*position[3];
|
||||
vertex->position[3] = m[3]*position[0] + m[7]*position[1] + m[11]*position[2] + m[15]*position[3];
|
||||
#endif
|
||||
|
||||
// Copy the attributes in the current vertex
|
||||
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
|
||||
@ -4164,6 +4277,7 @@ const char *swGetString(SWget name)
|
||||
case SW_RENDERER: result = "RLSW OpenGL Software Renderer"; break;
|
||||
case SW_VERSION: result = RLSW_VERSION; break;
|
||||
case SW_EXTENSIONS: result = "None"; break;
|
||||
case SW_SHADING_LANGUAGE_VERSION: result = "Not supported"; break;
|
||||
default: RLSW.errCode = SW_INVALID_ENUM; break;
|
||||
}
|
||||
|
||||
@ -5271,8 +5385,18 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||
int xEnd = (int)end->position[0];
|
||||
if (xStart == xEnd) return;
|
||||
|
||||
// Intercept the span bounds to ensure to not write before the framebuffer
|
||||
int xLoopStart = (xStart >= 0)? xStart : 0;
|
||||
int xLoopEnd = (xEnd <= RLSW.colorBuffer->width)? xEnd : RLSW.colorBuffer->width;
|
||||
if (xLoopStart >= xLoopEnd) return; // Nothing to draw
|
||||
|
||||
// Get the current row and skip if outside the framebuffer
|
||||
// Maybe this check is better suited elsewhere?
|
||||
int y = (int)start->position[1];
|
||||
if (y < 0 || y >= RLSW.colorBuffer->height) return;
|
||||
|
||||
// Compute the inverse horizontal distance along the X axis
|
||||
float dxRcp = 1.0f/(end->position[0] - start->position[0]);
|
||||
float dxRcp = sw_rcp(end->position[0] - start->position[0]);
|
||||
|
||||
// Compute the interpolation steps along the X axis
|
||||
float dWdx = (end->position[3] - start->position[3])*dxRcp;
|
||||
@ -5291,27 +5415,29 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||
#endif
|
||||
|
||||
// Compute the subpixel distance to traverse before the first pixel
|
||||
// Also step further into them to move away from the colorbuffer edge
|
||||
float xSubstep = 1.0f - sw_fract(start->position[0]);
|
||||
float dxStart = (float)(xLoopStart - xStart);
|
||||
float xOffset = xSubstep + dxStart;
|
||||
|
||||
// Initializing the interpolation starting values
|
||||
float w = start->position[3] + dWdx*xSubstep;
|
||||
float w = start->position[3] + dWdx*xOffset;
|
||||
float color[4] = {
|
||||
start->color[0] + dCdx[0]*xSubstep,
|
||||
start->color[1] + dCdx[1]*xSubstep,
|
||||
start->color[2] + dCdx[2]*xSubstep,
|
||||
start->color[3] + dCdx[3]*xSubstep
|
||||
start->color[0] + dCdx[0]*xOffset,
|
||||
start->color[1] + dCdx[1]*xOffset,
|
||||
start->color[2] + dCdx[2]*xOffset,
|
||||
start->color[3] + dCdx[3]*xOffset
|
||||
};
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
float z = start->position[2] + dZdx*xSubstep;
|
||||
float z = start->position[2] + dZdx*xOffset;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
float u = start->texcoord[0] + dUdx*xSubstep;
|
||||
float v = start->texcoord[1] + dVdx*xSubstep;
|
||||
float u = start->texcoord[0] + dUdx*xOffset;
|
||||
float v = start->texcoord[1] + dVdx*xOffset;
|
||||
#endif
|
||||
|
||||
// Pre-calculate the starting pointers for the framebuffer row
|
||||
int y = (int)start->position[1];
|
||||
int baseOffset = y*RLSW.colorBuffer->width + xStart;
|
||||
int baseOffset = y*RLSW.colorBuffer->width + xLoopStart;
|
||||
uint8_t *cPtr = (uint8_t *)(RLSW.colorBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
uint8_t *dPtr = (uint8_t *)(RLSW.depthBuffer->pixels) + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||
@ -5319,19 +5445,19 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||
|
||||
#define SW_AFFINE_BLOCK 16
|
||||
|
||||
int x = xStart;
|
||||
while (x < xEnd)
|
||||
int x = xLoopStart;
|
||||
while (x < xLoopEnd)
|
||||
{
|
||||
// Clamp last block to remaining pixels
|
||||
int blockEnd = x + SW_AFFINE_BLOCK;
|
||||
if (blockEnd > xEnd) blockEnd = xEnd;
|
||||
if (blockEnd > xLoopEnd) blockEnd = xLoopEnd;
|
||||
float blockLenF = (float)(blockEnd - x);
|
||||
float blockLenRcp = 1.0f/blockLenF;
|
||||
float blockLenRcp = sw_rcp(blockLenF);
|
||||
|
||||
// Only 2 '1/w' here; none inside the pixel loop
|
||||
float wRcpA = 1.0f/w;
|
||||
float wRcpA = sw_rcp(w);
|
||||
float wB = w + dWdx*blockLenF;
|
||||
float wRcpB = 1.0f/wB;
|
||||
float wRcpB = sw_rcp(wB);
|
||||
|
||||
// Perspective-correct color at both block endpoints, then affine gradient
|
||||
float srcColor[4] = {
|
||||
@ -5402,7 +5528,9 @@ static void SW_RASTER_TRIANGLE_SPAN(const sw_vertex_t *start, const sw_vertex_t
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
discard:
|
||||
#endif
|
||||
srcColor[0] += dSrcColordx[0];
|
||||
srcColor[1] += dSrcColordx[1];
|
||||
srcColor[2] += dSrcColordx[2];
|
||||
@ -5447,9 +5575,10 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
|
||||
if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
|
||||
|
||||
// Extracting coordinates from the sorted vertices
|
||||
float x0 = v0->position[0], y0 = v0->position[1];
|
||||
float x1 = v1->position[0], y1 = v1->position[1];
|
||||
float x2 = v2->position[0], y2 = v2->position[1];
|
||||
// Put x away for safe keeping; only y is used right now; silences warnings
|
||||
float y0 = v0->position[1];
|
||||
float y1 = v1->position[1];
|
||||
float y2 = v2->position[1];
|
||||
|
||||
// Compute height differences
|
||||
float h02 = y2 - y0;
|
||||
@ -5459,9 +5588,9 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
|
||||
if (h02 < 1e-6f) return;
|
||||
|
||||
// Inverse edge dy for per-edge dV/dy (scanline interpolation)
|
||||
float h02Rcp = 1.0f/h02;
|
||||
float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f;
|
||||
float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f;
|
||||
float h02Rcp = sw_rcp(h02);
|
||||
float h01Rcp = (h01 > 1e-6f)? sw_rcp(h01) : 0.0f;
|
||||
float h12Rcp = (h12 > 1e-6f)? sw_rcp(h12) : 0.0f;
|
||||
|
||||
// Compute gradients for each side of the triangle
|
||||
sw_vertex_t dVXdy02, dVXdy01, dVXdy12;
|
||||
@ -5556,12 +5685,20 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||
int xMax = (int)br->position[0];
|
||||
int yMax = (int)br->position[1];
|
||||
|
||||
// Exit early if no pixels to draw. Use these later for loop boundaries
|
||||
int yLoopMin = (yMin >= 0)? yMin : 0;
|
||||
int xLoopMin = (xMin >= 0)? xMin : 0;
|
||||
int yLoopMax = (yMax <= RLSW.colorBuffer->height)? yMax : RLSW.colorBuffer->height;
|
||||
int xLoopMax = (xMax <= RLSW.colorBuffer->width)? xMax : RLSW.colorBuffer->width;
|
||||
|
||||
if (yLoopMin >= yLoopMax || xLoopMin >= xLoopMax) return;
|
||||
|
||||
float w = (float)(xMax - xMin);
|
||||
float h = (float)(yMax - yMin);
|
||||
if ((w <= 0) || (h <= 0)) return;
|
||||
|
||||
float wRcp = 1.0f/w;
|
||||
float hRcp = 1.0f/h;
|
||||
float wRcp = sw_rcp(w);
|
||||
float hRcp = sw_rcp(h);
|
||||
|
||||
// Subpixel corrections
|
||||
float xSubstep = 1.0f - sw_fract(tl->position[0]);
|
||||
@ -5609,21 +5746,44 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||
uint8_t *dPixels = RLSW.depthBuffer->pixels;
|
||||
#endif
|
||||
|
||||
for (int y = yMin; y < yMax; y++)
|
||||
// Calculate the distance the in-bounds boundary is from the quad's edges, only on the left and top
|
||||
float dxMin = (float)(xLoopMin - xMin);
|
||||
float dyMin = (float)(yLoopMin - yMin);
|
||||
|
||||
// Correct our start by how far it's clipped outside the framebuffer
|
||||
cRow[0] += dCdx[0]*dxMin + dCdy[0]*dyMin;
|
||||
cRow[1] += dCdx[1]*dxMin + dCdy[1]*dyMin;
|
||||
cRow[2] += dCdx[2]*dxMin + dCdy[2]*dyMin;
|
||||
cRow[3] += dCdx[3]*dxMin + dCdy[3]*dyMin;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
zRow += dZdy*dyMin + dZdx*dxMin;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
uRow += dUdy*dyMin + dUdx*dxMin;
|
||||
vRow += dVdy*dyMin + dVdx*dxMin;
|
||||
#endif
|
||||
|
||||
for (int y = yLoopMin; y < yLoopMax; y++)
|
||||
{
|
||||
int baseOffset = y*stride + xMin;
|
||||
int baseOffset = y*stride + xLoopMin;
|
||||
uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||
// Copy the cursors without destroying the offset maths
|
||||
float z = zRow;
|
||||
#endif
|
||||
#ifdef SW_ENABLE_TEXTURE
|
||||
float u = uRow;
|
||||
float v = vRow;
|
||||
#endif
|
||||
float color[4] = { cRow[0], cRow[1], cRow[2], cRow[3] };
|
||||
float color[4] = {
|
||||
cRow[0],
|
||||
cRow[1],
|
||||
cRow[2],
|
||||
cRow[3]
|
||||
};
|
||||
|
||||
for (int x = xMin; x < xMax; x++)
|
||||
for (int x = xLoopMin; x < xLoopMax; x++)
|
||||
{
|
||||
float srcColor[4] = { color[0], color[1], color[2], color[3] };
|
||||
|
||||
@ -5659,7 +5819,10 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
discard:
|
||||
#endif
|
||||
// Move one pixel over without touching the original "start offset"
|
||||
color[0] += dCdx[0];
|
||||
color[1] += dCdx[1];
|
||||
color[2] += dCdx[2];
|
||||
@ -5682,6 +5845,9 @@ static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||
cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
|
||||
}
|
||||
|
||||
// The for loop is clamped to the right side of the screen
|
||||
// However, these cursor start vars are still on the left
|
||||
// That's fine, advancing to the next row
|
||||
cRow[0] += dCdy[0];
|
||||
cRow[1] += dCdy[1];
|
||||
cRow[2] += dCdy[2];
|
||||
@ -5746,7 +5912,7 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1)
|
||||
// Compute per pixel increments
|
||||
float xInc = dx/steps;
|
||||
float yInc = dy/steps;
|
||||
float stepRcp = 1.0f/steps;
|
||||
float stepRcp = sw_rcp(steps);
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
float zInc = (v1->position[2] - v0->position[2])*stepRcp;
|
||||
#endif
|
||||
@ -5812,7 +5978,9 @@ static void SW_RASTER_LINE(const sw_vertex_t *v0, const sw_vertex_t *v1)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
discard:
|
||||
#endif
|
||||
x += xInc;
|
||||
y += yInc;
|
||||
#ifdef SW_ENABLE_DEPTH_TEST
|
||||
|
||||
10
src/external/rprand.h
vendored
10
src/external/rprand.h
vendored
@ -1,6 +1,6 @@
|
||||
/**********************************************************************************************
|
||||
*
|
||||
* rprand v1.0 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
|
||||
* rprand v1.1 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
|
||||
*
|
||||
* FEATURES:
|
||||
* - Pseudo-random values generation, 32 bits: [0..4294967295]
|
||||
@ -118,6 +118,7 @@ extern "C" { // Prevents name mangling of functions
|
||||
//----------------------------------------------------------------------------------
|
||||
RPRANDAPI void rprand_set_seed(unsigned long long seed); // Set rprand_state for Xoshiro128**, seed is 64bit
|
||||
RPRANDAPI int rprand_get_value(int min, int max); // Get random value within a range, min and max included
|
||||
RPRANDAPI int rprand_get_value_raw(void); // Get random value, Xoshiro128** generator (uses global rprand_state)
|
||||
|
||||
RPRANDAPI int *rprand_load_sequence(unsigned int count, int min, int max); // Load pseudo-random numbers sequence with no duplicates
|
||||
RPRANDAPI void rprand_unload_sequence(int *sequence); // Unload pseudo-random numbers sequence
|
||||
@ -186,6 +187,13 @@ int rprand_get_value(int min, int max)
|
||||
return value;
|
||||
}
|
||||
|
||||
int rprand_get_value_raw(void)
|
||||
{
|
||||
int value = rprand_xoshiro();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Load pseudo-random numbers sequence with no duplicates, min and max included
|
||||
int *rprand_load_sequence(unsigned int count, int min, int max)
|
||||
{
|
||||
|
||||
12
src/external/win32_clipboard.h
vendored
12
src/external/win32_clipboard.h
vendored
@ -4,14 +4,14 @@
|
||||
|
||||
#ifndef WIN32_CLIPBOARD_
|
||||
#define WIN32_CLIPBOARD_
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize);
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize);
|
||||
#endif // WIN32_CLIPBOARD_
|
||||
|
||||
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
|
||||
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
|
||||
@ -213,7 +213,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih); // Get pixel data offset fr
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize)
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize)
|
||||
{
|
||||
unsigned char *bmpData = NULL;
|
||||
|
||||
@ -228,7 +228,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
*width = bmpInfoHeader->biWidth;
|
||||
*height = bmpInfoHeader->biHeight;
|
||||
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
||||
if (clipDataSize >= sizeof(BITMAPINFOHEADER))
|
||||
if ((clipDataSize >= sizeof(BITMAPINFOHEADER)) && (clipDataSize < INT_MAX))
|
||||
{
|
||||
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
||||
|
||||
@ -236,7 +236,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
//------------------------------------------------------------------------
|
||||
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
||||
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
||||
*dataSize = bmpFileSize;
|
||||
*dataSize = (unsigned int)bmpFileSize;
|
||||
|
||||
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
|
||||
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
||||
@ -254,7 +254,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "Clipboard data is malformed");
|
||||
TRACELOG(LOG_WARNING, "Clipboard data is not supported (>2GB?)");
|
||||
GlobalUnlock(clipHandle);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ double GetTime(void)
|
||||
double time = 0.0;
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
@ -1273,20 +1273,19 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||
int32_t keycode = AKeyEvent_getKeyCode(event);
|
||||
//int32_t AKeyEvent_getMetaState(event);
|
||||
|
||||
// Handle gamepad button presses and releases
|
||||
// NOTE: Skip gamepad handling if this is a keyboard event, as some devices
|
||||
// report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags
|
||||
if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
||||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
|
||||
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
|
||||
// Handle gamepad button presses and releases. AOSP stamps the
|
||||
// KEYBOARD source bit on every key event from a gamepad, so
|
||||
// discriminate on the keycode rather than gating on source bits.
|
||||
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
|
||||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
|
||||
{
|
||||
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
||||
|
||||
if (button != GAMEPAD_BUTTON_UNKNOWN)
|
||||
{
|
||||
// Assuming a single gamepad, "detected" on its input event
|
||||
CORE.Input.Gamepad.ready[0] = true;
|
||||
|
||||
GamepadButton button = AndroidTranslateGamepadButton(keycode);
|
||||
|
||||
if (button == GAMEPAD_BUTTON_UNKNOWN) return 1;
|
||||
|
||||
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[0][button] = 1;
|
||||
@ -1295,6 +1294,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||
|
||||
return 1; // Handled gamepad button
|
||||
}
|
||||
// Unknown keycode: fall through to the keyboard handler below.
|
||||
}
|
||||
|
||||
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
|
||||
if (key != KEY_NULL)
|
||||
|
||||
@ -1042,11 +1042,6 @@ const char *GetClipboardText(void)
|
||||
return glfwGetClipboardString(platform.handle);
|
||||
}
|
||||
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && defined(__linux__) && defined(_GLFW_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
// Get clipboard image
|
||||
Image GetClipboardImage(void)
|
||||
{
|
||||
@ -1054,7 +1049,8 @@ Image GetClipboardImage(void)
|
||||
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||
#if defined(_WIN32)
|
||||
unsigned long long int dataSize = 0;
|
||||
|
||||
unsigned int dataSize = 0;
|
||||
void *bmpData = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
@ -1065,32 +1061,30 @@ Image GetClipboardImage(void)
|
||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize);
|
||||
|
||||
#elif defined(__linux__) && defined(_GLFW_X11)
|
||||
|
||||
// REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
if (!dpy) return image;
|
||||
|
||||
Window root = DefaultRootWindow(dpy);
|
||||
Window win = XCreateSimpleWindow(
|
||||
dpy, // The connection to the X Server
|
||||
root, // The 'Parent' window (usually the desktop/root)
|
||||
0, 0, // X and Y position on the screen
|
||||
1, 1, // Width and Height (1x1 pixel)
|
||||
0, // Border width
|
||||
0, // Border color
|
||||
0 // Background color
|
||||
);
|
||||
static Atom clipboard = 0;
|
||||
static Atom targetType = 0;
|
||||
static Atom property = 0;
|
||||
|
||||
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False);
|
||||
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG
|
||||
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False);
|
||||
Display *display = glfwGetX11Display();
|
||||
XID window = glfwGetX11Window(platform.handle);
|
||||
|
||||
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER"
|
||||
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime);
|
||||
// Lazy-load X11 atoms
|
||||
if(clipboard == 0)
|
||||
{
|
||||
clipboard = XInternAtom(display, "CLIPBOARD", False);
|
||||
targetType = XInternAtom(display, "image/png", False);
|
||||
property = XInternAtom(display, "RAYLIB_CLIPBOARD_MANAGER", False);
|
||||
}
|
||||
|
||||
XConvertSelection(display, clipboard, targetType, property, window, CurrentTime);
|
||||
XSync(display, 0);
|
||||
|
||||
// Wait for the SelectionNotify event
|
||||
XEvent ev = { 0 };
|
||||
XNextEvent(dpy, &ev);
|
||||
|
||||
// Keep calling until we get SelectionNotify
|
||||
while (XCheckTypedEvent(display, SelectionNotify, &ev) == False);
|
||||
|
||||
Atom actualType = { 0 };
|
||||
int actualFormat = 0;
|
||||
@ -1098,8 +1092,7 @@ Image GetClipboardImage(void)
|
||||
unsigned long bytesAfter = 0;
|
||||
unsigned char *data = NULL;
|
||||
|
||||
// Read the data from our ghost window's property
|
||||
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType,
|
||||
XGetWindowProperty(display, window, property, 0, ~0L, False, AnyPropertyType,
|
||||
&actualType, &actualFormat, &nitems, &bytesAfter, &data);
|
||||
|
||||
if (data != NULL)
|
||||
@ -1108,11 +1101,9 @@ Image GetClipboardImage(void)
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
XDestroyWindow(dpy, win);
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
||||
#endif // defined(_WIN32)
|
||||
#endif // _WIN32
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
||||
91
src/platforms/rcore_desktop_rgfw.c
Executable file → Normal file
91
src/platforms/rcore_desktop_rgfw.c
Executable file → Normal file
@ -1024,15 +1024,15 @@ Image GetClipboardImage(void)
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||
#if defined(_WIN32)
|
||||
|
||||
unsigned long long int dataSize = 0; // moved into _WIN32 scope until other platforms gain support
|
||||
void *fileData = NULL; // moved into _WIN32 scope until other platforms gain support
|
||||
unsigned int dataSize = 0;
|
||||
void *fileData = NULL;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
|
||||
|
||||
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
|
||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize);
|
||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, (int)dataSize);
|
||||
|
||||
#elif defined(__linux__) && defined(DRGFW_X11)
|
||||
|
||||
@ -1082,7 +1082,7 @@ Image GetClipboardImage(void)
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
|
||||
#endif // defined(_WIN32)
|
||||
#endif // _WIN32
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
@ -1132,8 +1132,8 @@ void SwapScreenBuffer(void)
|
||||
{
|
||||
if (platform.surface)
|
||||
{
|
||||
// copy rlsw pixel data to the surface framebuffer
|
||||
swReadPixels(0, 0, platform.surfaceWidth, platform.surfaceHeight, SW_RGBA, SW_UNSIGNED_BYTE, platform.surfacePixels);
|
||||
// Copy rlsw pixel data to the surface framebuffer
|
||||
rlCopyFramebuffer(0, 0, platform.surfaceWidth, platform.surfaceHeight, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.surfacePixels);
|
||||
|
||||
// Mac wants a different pixel order. I cant seem to get this to work any other way
|
||||
#if defined(__APPLE__)
|
||||
@ -1677,10 +1677,62 @@ int InitPlatform(void)
|
||||
// Initialize RGFW internal global state, only required systems
|
||||
unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND;
|
||||
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder);
|
||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize);
|
||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus);
|
||||
|
||||
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
|
||||
{
|
||||
FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
|
||||
}
|
||||
|
||||
// Check window creation flags
|
||||
|
||||
// Init window in fullscreen mode if requested
|
||||
// NOTE: Keeping original screen size for toggle
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
|
||||
{
|
||||
FLAG_SET(flags, RGFW_windowFullscreen);
|
||||
int result = RGFW_init();
|
||||
if (result != 0)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RGFW: Failed to initialize RGFW");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE: Fullscreen applications default to the primary monitor
|
||||
RGFW_monitor *monitor = RGFW_getPrimaryMonitor();
|
||||
if (!monitor)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RGFW: Failed to get primary monitor");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Default display resolution to that of the current mode
|
||||
CORE.Window.display.width = monitor->mode.w;
|
||||
CORE.Window.display.height = monitor->mode.h;
|
||||
|
||||
// Check if user requested some screen size
|
||||
if ((CORE.Window.screen.width == 0) || (CORE.Window.screen.height == 0))
|
||||
{
|
||||
// Set some default screen size in case user decides to exit fullscreen mode
|
||||
CORE.Window.previousScreen.width = 800;
|
||||
CORE.Window.previousScreen.height = 450;
|
||||
CORE.Window.previousPosition.x = (CORE.Window.display.width - CORE.Window.previousScreen.width)/2;
|
||||
CORE.Window.previousPosition.y = (CORE.Window.display.height - CORE.Window.previousScreen.height)/2;
|
||||
|
||||
// Set screen width/height to the display width/height
|
||||
if (CORE.Window.screen.width == 0) CORE.Window.screen.width = CORE.Window.display.width;
|
||||
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
CORE.Window.screen = CORE.Window.display;
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
|
||||
@ -1688,16 +1740,16 @@ int InitPlatform(void)
|
||||
FLAG_SET(flags, RGFW_windowedFullscreen);
|
||||
}
|
||||
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder);
|
||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) FLAG_SET(flags, RGFW_windowFullscreen);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize);
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
#if !defined(__APPLE__)
|
||||
CORE.Window.screen.width = CORE.Window.screen.width*GetWindowScaleDPI().x;
|
||||
CORE.Window.screen.height = CORE.Window.screen.height*GetWindowScaleDPI().y;
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: Some OpenGL context attributes must be set before window creation
|
||||
// Check selection OpenGL version
|
||||
|
||||
RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL();
|
||||
if (rlGetVersion() == RL_OPENGL_21)
|
||||
{
|
||||
@ -1720,20 +1772,9 @@ int InitPlatform(void)
|
||||
hints->minor = 1;
|
||||
hints->renderer = RGFW_glSoftware;
|
||||
}
|
||||
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) hints->samples = 4;
|
||||
|
||||
if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus);
|
||||
|
||||
if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
#if !defined(__APPLE__)
|
||||
CORE.Window.screen.width = CORE.Window.screen.width * GetWindowScaleDPI().x;
|
||||
CORE.Window.screen.height = CORE.Window.screen.height * GetWindowScaleDPI().y;
|
||||
#endif
|
||||
}
|
||||
|
||||
RGFW_setGlobalHints_OpenGL(hints);
|
||||
|
||||
platform.window = RGFW_createWindow((CORE.Window.title != 0)? CORE.Window.title : " ", 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, flags | RGFW_windowOpenGL);
|
||||
|
||||
#ifndef PLATFORM_WEB_RGFW
|
||||
|
||||
@ -1526,7 +1526,6 @@ int InitPlatform(void)
|
||||
if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr);
|
||||
}
|
||||
*/
|
||||
|
||||
HINSTANCE hInstance = GetModuleHandleW(0);
|
||||
|
||||
// Define window class
|
||||
|
||||
@ -266,9 +266,12 @@ static void PollKeyboardEvents(void); // Process evdev keyboard events
|
||||
static void PollGamepadEvents(void); // Process evdev gamepad events
|
||||
static void PollMouseEvents(void); // Process evdev mouse events
|
||||
|
||||
// Not used by software rendering.
|
||||
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
|
||||
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
|
||||
static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list
|
||||
#endif
|
||||
|
||||
static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform())
|
||||
|
||||
@ -1003,7 +1006,7 @@ double GetTime(void)
|
||||
double time = 0.0;
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
@ -2560,6 +2563,7 @@ static void PollMouseEvents(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
|
||||
// Search matching DRM mode in connector's mode list
|
||||
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)
|
||||
{
|
||||
@ -2648,6 +2652,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
|
||||
|
||||
return nearestIndex;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compute framebuffer size relative to screen size and display size
|
||||
// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified
|
||||
|
||||
@ -364,14 +364,18 @@ double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER now = { 0 };
|
||||
QueryPerformanceCounter(&now);
|
||||
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||
LARGE_INTEGER currentTicks = { 0 };
|
||||
QueryPerformanceCounter(¤tTicks);
|
||||
|
||||
time = (double)(currentTicks.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
#elif defined(PICO_RP2350)
|
||||
time = (double)to_ms_since_boot(get_absolute_time())/1000.0;
|
||||
#endif
|
||||
return time;
|
||||
}
|
||||
|
||||
@ -341,9 +341,11 @@ void SwapScreenBuffer(void)
|
||||
double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
return time;
|
||||
|
||||
@ -858,7 +858,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||
{
|
||||
drmp3_config config = { 0 };
|
||||
unsigned long long int totalFrameCount = 0;
|
||||
unsigned long long totalFrameCount = 0;
|
||||
|
||||
// NOTE: Forcing conversion to 32bit float sample size on reading
|
||||
wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
|
||||
@ -868,7 +868,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
{
|
||||
wave.channels = config.channels;
|
||||
wave.sampleRate = config.sampleRate;
|
||||
wave.frameCount = (int)totalFrameCount;
|
||||
wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
||||
|
||||
@ -896,13 +896,13 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
#if SUPPORT_FILEFORMAT_FLAC
|
||||
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
||||
{
|
||||
unsigned long long int totalFrameCount = 0;
|
||||
unsigned long long totalFrameCount = 0;
|
||||
|
||||
// NOTE: Forcing conversion to 16bit sample size on reading
|
||||
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
||||
wave.sampleSize = 16;
|
||||
|
||||
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
|
||||
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
||||
}
|
||||
#endif
|
||||
@ -1048,6 +1048,7 @@ void UnloadSoundAlias(Sound alias)
|
||||
{
|
||||
UntrackAudioBuffer(alias.stream.buffer);
|
||||
ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
|
||||
RL_FREE(alias.stream.buffer->converterResidual);
|
||||
RL_FREE(alias.stream.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1164,7 +1164,7 @@ RLAPI bool ChangeDirectory(const char *dirPath); // Change wo
|
||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
|
||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`
|
||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'
|
||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||
|
||||
38
src/rcore.c
38
src/rcore.c
@ -385,7 +385,7 @@ typedef struct CoreData {
|
||||
double draw; // Time measure for frame draw (seconds)
|
||||
double frame; // Time measure for one frame (seconds)
|
||||
double target; // Desired time for one frame, if 0 not applied (seconds)
|
||||
unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds)
|
||||
unsigned long long base; // Base time measure for hi-res timer (ticks or nanoseconds)
|
||||
unsigned int frameCounter; // Frame counter (frames)
|
||||
|
||||
} Time;
|
||||
@ -442,18 +442,6 @@ typedef enum AutomationEventType {
|
||||
ACTION_SETTARGETFPS // param[0]: fps
|
||||
} AutomationEventType;
|
||||
|
||||
// Event type to config events flags
|
||||
// WARNING: Not used at the moment
|
||||
typedef enum {
|
||||
EVENT_INPUT_KEYBOARD = 0,
|
||||
EVENT_INPUT_MOUSE = 1,
|
||||
EVENT_INPUT_GAMEPAD = 2,
|
||||
EVENT_INPUT_TOUCH = 4,
|
||||
EVENT_INPUT_GESTURE = 8,
|
||||
EVENT_WINDOW = 16,
|
||||
EVENT_CUSTOM = 32
|
||||
} EventType;
|
||||
|
||||
// Event type name strings, required for export
|
||||
static const char *autoEventTypeName[] = {
|
||||
"EVENT_NONE",
|
||||
@ -482,16 +470,6 @@ static const char *autoEventTypeName[] = {
|
||||
"ACTION_SETTARGETFPS"
|
||||
};
|
||||
|
||||
/*
|
||||
// Automation event (24 bytes)
|
||||
// NOTE: Opaque struct, internal to raylib
|
||||
struct AutomationEvent {
|
||||
unsigned int frame; // Event frame
|
||||
unsigned int type; // Event type (AutomationEventType)
|
||||
int params[4]; // Event parameters (if required)
|
||||
};
|
||||
*/
|
||||
|
||||
static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer
|
||||
static bool automationEventRecording = false; // Recording automation events flag
|
||||
//static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing
|
||||
@ -528,11 +506,11 @@ __declspec(dllimport) void __stdcall Sleep(unsigned long msTimeout); // Required
|
||||
const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||
#endif
|
||||
|
||||
// NOTE: PLATFORM_DESKTOP defaults to GLFW backend
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#define PLATFORM_DESKTOP_GLFW
|
||||
#endif
|
||||
|
||||
|
||||
// Include platform-specific submodules
|
||||
#if defined(PLATFORM_DESKTOP_GLFW)
|
||||
#include "platforms/rcore_desktop_glfw.c"
|
||||
@ -2340,7 +2318,7 @@ bool FileExists(const char *fileName)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (ACCESS(fileName) != -1) result = true;
|
||||
if ((fileName != NULL) && (ACCESS(fileName) != -1)) result = true;
|
||||
|
||||
// NOTE: Alternatively, stat() can be used instead of access()
|
||||
//#include <sys/stat.h>
|
||||
@ -3475,8 +3453,8 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
hash[6] = 0x1f83d9ab;
|
||||
hash[7] = 0x5be0cd19;
|
||||
|
||||
const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8;
|
||||
unsigned long long int paddedSize = dataSize + sizeof(dataSize);
|
||||
const unsigned long long bitLen = 8ULL*dataSize;
|
||||
unsigned long long paddedSize = dataSize + sizeof(dataSize);
|
||||
paddedSize += (64 - (paddedSize%64));
|
||||
unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char));
|
||||
|
||||
@ -3487,7 +3465,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF;
|
||||
}
|
||||
|
||||
for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++)
|
||||
for (unsigned long long blockN = 0; blockN < paddedSize/64; blockN++)
|
||||
{
|
||||
unsigned int a = hash[0];
|
||||
unsigned int b = hash[1];
|
||||
@ -3509,7 +3487,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
}
|
||||
for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16];
|
||||
|
||||
for (unsigned long long int t = 0; t < 64; t++)
|
||||
for (int t = 0; t < 64; t++)
|
||||
{
|
||||
unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25));
|
||||
unsigned int ch = ((e & f) ^ (~e & g));
|
||||
@ -4241,7 +4219,7 @@ void InitTimer(void)
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
||||
{
|
||||
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;
|
||||
CORE.Time.base = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
||||
#endif
|
||||
|
||||
@ -157,8 +157,8 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
// Functions required to query time on Windows
|
||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||
int __stdcall QueryPerformanceCounter(unsigned long long *lpPerformanceCount);
|
||||
int __stdcall QueryPerformanceFrequency(unsigned long long *lpFrequency);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@ -518,37 +518,36 @@ static double rgGetCurrentTime(void)
|
||||
time = GetTime();
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
unsigned long long int clockFrequency, currentTime;
|
||||
unsigned long long clockFrequency = 0;
|
||||
unsigned long long currentClockTicks = 0;
|
||||
|
||||
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||
QueryPerformanceCounter(¤tTime);
|
||||
QueryPerformanceCounter(¤tClockTicks);
|
||||
|
||||
time = (double)currentTime/clockFrequency; // Time in seconds
|
||||
time = (double)currentClockTicks/clockFrequency; // Time in seconds
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
// NOTE: Only for Linux-based systems
|
||||
struct timespec now;
|
||||
struct timespec now = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
|
||||
time = ((double)nowTime*1e-9); // Time in seconds
|
||||
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
|
||||
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
|
||||
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t now;
|
||||
clock_serv_t cclock = { 0 };
|
||||
mach_timespec_t now = { 0 };
|
||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||
|
||||
// NOTE: OS X does not have clock_gettime(), using clock_get_time()
|
||||
clock_get_time(cclock, &now);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
|
||||
time = ((double)nowTime*1e-9); // Time in seconds
|
||||
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -3647,7 +3647,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
#else // defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#else // GRAPHICS_API_OPENGL_ES2
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
|
||||
@ -361,7 +361,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
|
||||
segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
|
||||
segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
|
||||
|
||||
if (segments <= 0) segments = minSegments;
|
||||
}
|
||||
@ -453,7 +453,7 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
|
||||
segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
|
||||
segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
|
||||
|
||||
if (segments <= 0) segments = minSegments;
|
||||
}
|
||||
@ -579,7 +579,7 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
|
||||
segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
|
||||
segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
|
||||
|
||||
if (segments <= 0) segments = minSegments;
|
||||
}
|
||||
@ -670,7 +670,7 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
|
||||
segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
|
||||
segments = (int)ceilf((endAngle - startAngle)*(2*PI/th)/360.0f);
|
||||
|
||||
if (segments <= 0) segments = minSegments;
|
||||
}
|
||||
@ -960,7 +960,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
|
||||
segments = (int)(ceilf(2*PI/th)/4.0f);
|
||||
segments = (int)ceilf((2*PI/th)/4.0f);
|
||||
if (segments <= 0) segments = 4;
|
||||
}
|
||||
|
||||
@ -1195,7 +1195,7 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
|
||||
{
|
||||
// Calculate the maximum angle between segments based on the error rate (usually 0.5f)
|
||||
float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
|
||||
segments = (int)(ceilf(2*PI/th)/2.0f);
|
||||
segments = (int)ceilf((2*PI/th)/4.0f);
|
||||
if (segments <= 0) segments = 4;
|
||||
}
|
||||
|
||||
|
||||
@ -580,8 +580,13 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
|
||||
TRACELOG(LOG_INFO, "FONT: Data loaded successfully (%i pixel size | %i glyphs)", font.baseSize, font.glyphCount);
|
||||
}
|
||||
else font = GetFontDefault();
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FONT: Font is not supported by LoadFontEx/LoadFontFromMemory or no glyphs found, reverted to default font");
|
||||
font = GetFontDefault();
|
||||
}
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "FONT: Font is not supported by LoadFontEx/LoadFontFromMemory or no glyphs found, reverted to default font");
|
||||
font = GetFontDefault();
|
||||
#endif
|
||||
|
||||
|
||||
@ -675,13 +675,12 @@ int main(int argc, char *argv[])
|
||||
// WARNING 2: raylib.a and raylib.web.a must be available when compiling locally
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", GetFileNameWithoutExt(inFileName));
|
||||
//putenv("RAYLIB_DIR=C:\\GitHub\\raylib");
|
||||
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
|
||||
#else
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", GetFileNameWithoutExt(inFileName));
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
|
||||
#endif
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
|
||||
|
||||
// Update generated .html metadata
|
||||
LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exName));
|
||||
UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName),
|
||||
@ -778,10 +777,9 @@ int main(int argc, char *argv[])
|
||||
// WARNING: EMSDK_PATH must be set to proper location when calling from GitHub Actions
|
||||
#if defined(_WIN32)
|
||||
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename));
|
||||
#else
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename));
|
||||
#endif
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename));
|
||||
|
||||
// Update generated .html metadata
|
||||
UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exRename),
|
||||
TextFormat("%s/%s/%s.c", exBasePath, exCategory, exRename));
|
||||
@ -917,7 +915,7 @@ int main(int argc, char *argv[])
|
||||
// Set required environment variables
|
||||
//putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
|
||||
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
//putenv("MAKE=mingw32-make");
|
||||
//putenv("MAKE=make");
|
||||
//ChangeDirectory(exBasePath);
|
||||
#endif
|
||||
for (int i = 0; i < exBuildListCount; i++)
|
||||
@ -933,7 +931,7 @@ int main(int argc, char *argv[])
|
||||
// Build example for PLATFORM_DESKTOP
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: Win32)\n", exName);
|
||||
system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
|
||||
system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
|
||||
#elif defined(PLATFORM_DRM)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_DRM (Host: POSIX)\n", exName);
|
||||
system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DRM -B > %s/%s/logs/%s.build.log 2>&1",
|
||||
@ -949,13 +947,9 @@ int main(int argc, char *argv[])
|
||||
// Build: raylib.com/examples/<category>/<category>_example_name.data
|
||||
// Build: raylib.com/examples/<category>/<category>_example_name.wasm
|
||||
// Build: raylib.com/examples/<category>/<category>_example_name.js
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exName);
|
||||
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
|
||||
#else
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exName);
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB\n", exName);
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
|
||||
#endif
|
||||
|
||||
// Update generated .html metadata
|
||||
LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exName));
|
||||
UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName),
|
||||
@ -1312,11 +1306,10 @@ int main(int argc, char *argv[])
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exInfo->name);
|
||||
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name));
|
||||
#else
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exInfo->name);
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name));
|
||||
#endif
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name));
|
||||
|
||||
// Update generated .html metadata
|
||||
LOG("INFO: [%s.html] Updating HTML Metadata...\n", exInfo->name);
|
||||
@ -1495,7 +1488,7 @@ int main(int argc, char *argv[])
|
||||
// Set required environment variables
|
||||
//putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
|
||||
//_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
//putenv("MAKE=mingw32-make");
|
||||
//putenv("MAKE=make");
|
||||
//ChangeDirectory(exBasePath);
|
||||
//_putenv("MAKE_PATH=C:\\raylib\\w64devkit\\bin");
|
||||
//_putenv("EMSDK_PATH = C:\\raylib\\emsdk");
|
||||
@ -1592,7 +1585,7 @@ int main(int argc, char *argv[])
|
||||
// Build: raylib.com/examples/<category>/<category>_example_name.js
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exName);
|
||||
system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B > %s/%s/logs/%s.build.log 2>&1",
|
||||
system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B > %s/%s/logs/%s.build.log 2>&1",
|
||||
exBasePath, exCategory, exName, exBasePath, exCategory, exName));
|
||||
#else
|
||||
LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exName);
|
||||
@ -1641,13 +1634,13 @@ int main(int argc, char *argv[])
|
||||
// Set required environment variables
|
||||
//putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
|
||||
_putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
|
||||
//putenv("MAKE=mingw32-make");
|
||||
//putenv("MAKE=make");
|
||||
//ChangeDirectory(exBasePath);
|
||||
#endif
|
||||
// Build example for PLATFORM_DESKTOP
|
||||
#if defined(_WIN32)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: Win32)\n", exName);
|
||||
system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B > %s/%s/logs/%s.build.log 2>&1",
|
||||
system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B > %s/%s/logs/%s.build.log 2>&1",
|
||||
exBasePath, exCategory, exName, exBasePath, exCategory, exName));
|
||||
#elif defined(PLATFORM_DRM)
|
||||
LOG("INFO: [%s] Building example for PLATFORM_DRM (Host: POSIX)\n", exName);
|
||||
|
||||
@ -4696,7 +4696,7 @@
|
||||
},
|
||||
{
|
||||
"name": "LoadDirectoryFilesEx",
|
||||
"description": "Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`",
|
||||
"description": "Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'",
|
||||
"returnType": "FilePathList",
|
||||
"params": [
|
||||
{
|
||||
|
||||
@ -4207,7 +4207,7 @@ return {
|
||||
},
|
||||
{
|
||||
name = "LoadDirectoryFilesEx",
|
||||
description = "Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`",
|
||||
description = "Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'",
|
||||
returnType = "FilePathList",
|
||||
params = {
|
||||
{type = "const char *", name = "basePath"},
|
||||
|
||||
@ -1789,7 +1789,7 @@ Function 146: LoadDirectoryFiles() (1 input parameters)
|
||||
Function 147: LoadDirectoryFilesEx() (3 input parameters)
|
||||
Name: LoadDirectoryFilesEx
|
||||
Return type: FilePathList
|
||||
Description: Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`
|
||||
Description: Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'
|
||||
Param[1]: basePath (type: const char *)
|
||||
Param[2]: filter (type: const char *)
|
||||
Param[3]: scanSubdirs (type: bool)
|
||||
|
||||
@ -1125,7 +1125,7 @@
|
||||
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths, files and directories, no subdirs scan">
|
||||
<Param type="const char *" name="dirPath" desc="" />
|
||||
</Function>
|
||||
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and subdir scan; some filters available: `*.*`,`FILES*`,`DIRS*`">
|
||||
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'">
|
||||
<Param type="const char *" name="basePath" desc="" />
|
||||
<Param type="const char *" name="filter" desc="" />
|
||||
<Param type="bool" name="scanSubdirs" desc="" />
|
||||
|
||||
Reference in New Issue
Block a user