Merge branch 'master' into more-spline-functions
This commit is contained in:
commit
b80920b1ee
30 changed files with 20425 additions and 18426 deletions
|
|
@ -8,7 +8,7 @@ include(JoinPaths)
|
|||
|
||||
# Sets build type if not set by now
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
if(RAYLIB_IS_MAIN)
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
set(default_build_type Debug)
|
||||
else()
|
||||
message(WARNING "Default build type is not set (CMAKE_BUILD_TYPE)")
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ OBJS = rcore.o \
|
|||
rshapes.o \
|
||||
rtextures.o \
|
||||
rtext.o \
|
||||
utils.o
|
||||
utils.o
|
||||
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(USE_EXTERNAL_GLFW),FALSE)
|
||||
|
|
@ -868,7 +868,7 @@ clean: clean_shell_$(PLATFORM_SHELL)
|
|||
@echo "removed all generated files!"
|
||||
|
||||
clean_shell_sh:
|
||||
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h
|
||||
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).web.a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c $(RAYLIB_RELEASE_PATH)/*-protocol.h $(RAYLIB_RELEASE_PATH)/*-protocol-code.h
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
|
||||
endif
|
||||
|
|
@ -879,6 +879,7 @@ clean_shell_cmd:
|
|||
del *.o /s
|
||||
cd $(RAYLIB_RELEASE_PATH) & \
|
||||
del lib$(RAYLIB_LIB_NAME).a /s & \
|
||||
del lib$(RAYLIB_LIB_NAME).web.a /s & \
|
||||
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
|
||||
del $(RAYLIB_LIB_NAME).dll /s & \
|
||||
del raygui.c /s & \
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@
|
|||
#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
|
||||
#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
|
||||
#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
|
||||
#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
|
||||
#define MAX_GAMEPAD_AXES 8 // Maximum number of axes supported (per gamepad)
|
||||
#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
|
||||
#define MAX_GAMEPAD_VIBRATION_TIME 2.0f // Maximum vibration time in seconds
|
||||
#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
|
||||
|
|
@ -136,8 +136,8 @@
|
|||
|
||||
#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
|
||||
|
||||
#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
|
||||
#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
|
||||
#define RL_CULL_DISTANCE_NEAR 0.001 // Default projection matrix near cull distance
|
||||
#define RL_CULL_DISTANCE_FAR 10000.0 // Default projection matrix far cull distance
|
||||
|
||||
// Default shader vertex attribute locations
|
||||
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
|
||||
|
|
@ -189,7 +189,7 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
// Module: rtextures - Configuration Flags
|
||||
//------------------------------------------------------------------------------------
|
||||
// Selecte desired fileformats to be supported for image data loading
|
||||
// Selected desired fileformats to be supported for image data loading
|
||||
#define SUPPORT_FILEFORMAT_PNG 1
|
||||
//#define SUPPORT_FILEFORMAT_BMP 1
|
||||
//#define SUPPORT_FILEFORMAT_TGA 1
|
||||
|
|
|
|||
21452
src/external/RGFW.h
vendored
21452
src/external/RGFW.h
vendored
File diff suppressed because it is too large
Load diff
462
src/external/dr_flac.h
vendored
462
src/external/dr_flac.h
vendored
|
|
@ -1,121 +1,12 @@
|
|||
/*
|
||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_flac - v0.12.42 - 2023-11-02
|
||||
dr_flac - v0.13.0 - TBD
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
GitHub: https://github.com/mackron/dr_libs
|
||||
*/
|
||||
|
||||
/*
|
||||
RELEASE NOTES - v0.12.0
|
||||
=======================
|
||||
Version 0.12.0 has breaking API changes including changes to the existing API and the removal of deprecated APIs.
|
||||
|
||||
|
||||
Improved Client-Defined Memory Allocation
|
||||
-----------------------------------------
|
||||
The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
|
||||
existing system of DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE are still in place and will be used by default when no custom
|
||||
allocation callbacks are specified.
|
||||
|
||||
To use the new system, you pass in a pointer to a drflac_allocation_callbacks object to drflac_open() and family, like this:
|
||||
|
||||
void* my_malloc(size_t sz, void* pUserData)
|
||||
{
|
||||
return malloc(sz);
|
||||
}
|
||||
void* my_realloc(void* p, size_t sz, void* pUserData)
|
||||
{
|
||||
return realloc(p, sz);
|
||||
}
|
||||
void my_free(void* p, void* pUserData)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
drflac_allocation_callbacks allocationCallbacks;
|
||||
allocationCallbacks.pUserData = &myData;
|
||||
allocationCallbacks.onMalloc = my_malloc;
|
||||
allocationCallbacks.onRealloc = my_realloc;
|
||||
allocationCallbacks.onFree = my_free;
|
||||
drflac* pFlac = drflac_open_file("my_file.flac", &allocationCallbacks);
|
||||
|
||||
The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
|
||||
|
||||
Passing in null for the allocation callbacks object will cause dr_flac to use defaults which is the same as DRFLAC_MALLOC,
|
||||
DRFLAC_REALLOC and DRFLAC_FREE and the equivalent of how it worked in previous versions.
|
||||
|
||||
Every API that opens a drflac object now takes this extra parameter. These include the following:
|
||||
|
||||
drflac_open()
|
||||
drflac_open_relaxed()
|
||||
drflac_open_with_metadata()
|
||||
drflac_open_with_metadata_relaxed()
|
||||
drflac_open_file()
|
||||
drflac_open_file_with_metadata()
|
||||
drflac_open_memory()
|
||||
drflac_open_memory_with_metadata()
|
||||
drflac_open_and_read_pcm_frames_s32()
|
||||
drflac_open_and_read_pcm_frames_s16()
|
||||
drflac_open_and_read_pcm_frames_f32()
|
||||
drflac_open_file_and_read_pcm_frames_s32()
|
||||
drflac_open_file_and_read_pcm_frames_s16()
|
||||
drflac_open_file_and_read_pcm_frames_f32()
|
||||
drflac_open_memory_and_read_pcm_frames_s32()
|
||||
drflac_open_memory_and_read_pcm_frames_s16()
|
||||
drflac_open_memory_and_read_pcm_frames_f32()
|
||||
|
||||
|
||||
|
||||
Optimizations
|
||||
-------------
|
||||
Seeking performance has been greatly improved. A new binary search based seeking algorithm has been introduced which significantly
|
||||
improves performance over the brute force method which was used when no seek table was present. Seek table based seeking also takes
|
||||
advantage of the new binary search seeking system to further improve performance there as well. Note that this depends on CRC which
|
||||
means it will be disabled when DR_FLAC_NO_CRC is used.
|
||||
|
||||
The SSE4.1 pipeline has been cleaned up and optimized. You should see some improvements with decoding speed of 24-bit files in
|
||||
particular. 16-bit streams should also see some improvement.
|
||||
|
||||
drflac_read_pcm_frames_s16() has been optimized. Previously this sat on top of drflac_read_pcm_frames_s32() and performed it's s32
|
||||
to s16 conversion in a second pass. This is now all done in a single pass. This includes SSE2 and ARM NEON optimized paths.
|
||||
|
||||
A minor optimization has been implemented for drflac_read_pcm_frames_s32(). This will now use an SSE2 optimized pipeline for stereo
|
||||
channel reconstruction which is the last part of the decoding process.
|
||||
|
||||
The ARM build has seen a few improvements. The CLZ (count leading zeroes) and REV (byte swap) instructions are now used when
|
||||
compiling with GCC and Clang which is achieved using inline assembly. The CLZ instruction requires ARM architecture version 5 at
|
||||
compile time and the REV instruction requires ARM architecture version 6.
|
||||
|
||||
An ARM NEON optimized pipeline has been implemented. To enable this you'll need to add -mfpu=neon to the command line when compiling.
|
||||
|
||||
|
||||
Removed APIs
|
||||
------------
|
||||
The following APIs were deprecated in version 0.11.0 and have been completely removed in version 0.12.0:
|
||||
|
||||
drflac_read_s32() -> drflac_read_pcm_frames_s32()
|
||||
drflac_read_s16() -> drflac_read_pcm_frames_s16()
|
||||
drflac_read_f32() -> drflac_read_pcm_frames_f32()
|
||||
drflac_seek_to_sample() -> drflac_seek_to_pcm_frame()
|
||||
drflac_open_and_decode_s32() -> drflac_open_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_s16() -> drflac_open_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_f32() -> drflac_open_and_read_pcm_frames_f32()
|
||||
drflac_open_and_decode_file_s32() -> drflac_open_file_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_file_s16() -> drflac_open_file_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_file_f32() -> drflac_open_file_and_read_pcm_frames_f32()
|
||||
drflac_open_and_decode_memory_s32() -> drflac_open_memory_and_read_pcm_frames_s32()
|
||||
drflac_open_and_decode_memory_s16() -> drflac_open_memory_and_read_pcm_frames_s16()
|
||||
drflac_open_and_decode_memory_f32() -> drflac_open_memroy_and_read_pcm_frames_f32()
|
||||
|
||||
Prior versions of dr_flac operated on a per-sample basis whereas now it operates on PCM frames. The removed APIs all relate
|
||||
to the old per-sample APIs. You now need to use the "pcm_frame" versions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Introduction
|
||||
============
|
||||
|
|
@ -179,7 +70,7 @@ reports metadata to the application through the use of a callback, and every met
|
|||
|
||||
The main opening APIs (`drflac_open()`, etc.) will fail if the header is not present. The presents a problem in certain scenarios such as broadcast style
|
||||
streams or internet radio where the header may not be present because the user has started playback mid-stream. To handle this, use the relaxed APIs:
|
||||
|
||||
|
||||
`drflac_open_relaxed()`
|
||||
`drflac_open_with_metadata_relaxed()`
|
||||
|
||||
|
|
@ -234,8 +125,8 @@ extern "C" {
|
|||
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
|
||||
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 12
|
||||
#define DRFLAC_VERSION_REVISION 42
|
||||
#define DRFLAC_VERSION_MINOR 13
|
||||
#define DRFLAC_VERSION_REVISION 0
|
||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
|
|
@ -348,11 +239,11 @@ but also more memory. In my testing there is diminishing returns after about 4KB
|
|||
#define DRFLAC_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
||||
#define DRFLAC_X64
|
||||
#elif defined(__i386) || defined(_M_IX86)
|
||||
#define DRFLAC_X86
|
||||
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
|
||||
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
|
||||
#define DRFLAC_ARM
|
||||
#endif
|
||||
/* End Architecture Detection */
|
||||
|
|
@ -406,8 +297,9 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
drflac_seek_origin_start,
|
||||
drflac_seek_origin_current
|
||||
DRFLAC_SEEK_SET,
|
||||
DRFLAC_SEEK_CUR,
|
||||
DRFLAC_SEEK_END
|
||||
} drflac_seek_origin;
|
||||
|
||||
/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
|
||||
|
|
@ -547,7 +439,7 @@ offset (in)
|
|||
The number of bytes to move, relative to the origin. Will never be negative.
|
||||
|
||||
origin (in)
|
||||
The origin of the seek - the current position or the start of the stream.
|
||||
The origin of the seek - the current position, the start of the stream, or the end of the stream.
|
||||
|
||||
|
||||
Return Value
|
||||
|
|
@ -557,14 +449,32 @@ Whether or not the seek was successful.
|
|||
|
||||
Remarks
|
||||
-------
|
||||
The offset will never be negative. Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be
|
||||
either drflac_seek_origin_start or drflac_seek_origin_current.
|
||||
Seeking relative to the start and the current position must always be supported. If seeking from the end of the stream is not supported, return DRFLAC_FALSE.
|
||||
|
||||
When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
|
||||
and handled by returning DRFLAC_FALSE.
|
||||
*/
|
||||
typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
|
||||
|
||||
/*
|
||||
Callback for when the current position in the stream needs to be retrieved.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pUserData (in)
|
||||
The user data that was passed to drflac_open() and family.
|
||||
|
||||
pCursor (out)
|
||||
A pointer to a variable to receive the current position in the stream.
|
||||
|
||||
|
||||
Return Value
|
||||
------------
|
||||
Whether or not the operation was successful.
|
||||
*/
|
||||
typedef drflac_bool32 (* drflac_tell_proc)(void* pUserData, drflac_int64* pCursor);
|
||||
|
||||
/*
|
||||
Callback for when a metadata block is read.
|
||||
|
||||
|
|
@ -603,6 +513,9 @@ typedef struct
|
|||
/* The function to call when the current read position needs to be moved. */
|
||||
drflac_seek_proc onSeek;
|
||||
|
||||
/* The function to call when the current read position needs to be retrieved. */
|
||||
drflac_tell_proc onTell;
|
||||
|
||||
/* The user data to pass around to onRead and onSeek. */
|
||||
void* pUserData;
|
||||
|
||||
|
|
@ -828,7 +741,7 @@ drflac_open_memory()
|
|||
drflac_open_with_metadata()
|
||||
drflac_close()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Opens a FLAC stream with relaxed validation of the header block.
|
||||
|
|
@ -869,7 +782,7 @@ force your `onRead` callback to return 0, which dr_flac will use as an indicator
|
|||
|
||||
Use `drflac_open_with_metadata_relaxed()` if you need access to metadata.
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
|
||||
|
|
@ -926,7 +839,7 @@ drflac_open_memory_with_metadata()
|
|||
drflac_open()
|
||||
drflac_close()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
|
||||
|
|
@ -936,7 +849,7 @@ See Also
|
|||
drflac_open_with_metadata()
|
||||
drflac_open_relaxed()
|
||||
*/
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/*
|
||||
Closes the given FLAC decoder.
|
||||
|
|
@ -1234,13 +1147,13 @@ read samples into a dynamically sized buffer on the heap until no samples are le
|
|||
|
||||
Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
|
||||
*/
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
#ifndef DR_FLAC_NO_STDIO
|
||||
/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
|
||||
|
|
@ -2960,25 +2873,25 @@ static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFro
|
|||
*/
|
||||
if (offsetFromStart > 0x7FFFFFFF) {
|
||||
drflac_uint64 bytesRemaining = offsetFromStart;
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
bytesRemaining -= 0x7FFFFFFF;
|
||||
|
||||
while (bytesRemaining > 0x7FFFFFFF) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
||||
if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
bytesRemaining -= 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (bytesRemaining > 0) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
|
||||
if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -5393,6 +5306,12 @@ static drflac_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe
|
|||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Default to 0 for the LPC order. It's important that we always set this to 0 for non LPC
|
||||
and FIXED subframes because we'll be using it in a generic validation check later.
|
||||
*/
|
||||
pSubframe->lpcOrder = 0;
|
||||
|
||||
type = (header & 0x7E) >> 1;
|
||||
if (type == 0) {
|
||||
pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT;
|
||||
|
|
@ -5465,6 +5384,18 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
|
|||
|
||||
pSubframe->pSamplesS32 = pDecodedSamplesOut;
|
||||
|
||||
/*
|
||||
pDecodedSamplesOut will be pointing to a buffer that was allocated with enough memory to store
|
||||
maxBlockSizeInPCMFrames samples (as specified in the FLAC header). We need to guard against an
|
||||
overflow here. At a higher level we are checking maxBlockSizeInPCMFrames from the header, but
|
||||
here we need to do an additional check to ensure this frame's block size fully encompasses any
|
||||
warmup samples which is determined by the LPC order. For non LPC and FIXED subframes, the LPC
|
||||
order will be have been set to 0 in drflac__read_subframe_header().
|
||||
*/
|
||||
if (frame->header.blockSizeInPCMFrames < pSubframe->lpcOrder) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
switch (pSubframe->subframeType)
|
||||
{
|
||||
case DRFLAC_SUBFRAME_CONSTANT:
|
||||
|
|
@ -6312,6 +6243,7 @@ typedef struct
|
|||
{
|
||||
drflac_read_proc onRead;
|
||||
drflac_seek_proc onSeek;
|
||||
drflac_tell_proc onTell;
|
||||
drflac_meta_proc onMeta;
|
||||
drflac_container container;
|
||||
void* pUserData;
|
||||
|
|
@ -6479,7 +6411,7 @@ static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbac
|
|||
}
|
||||
|
||||
|
||||
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
/*
|
||||
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
|
||||
|
|
@ -6489,6 +6421,8 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
drflac_uint64 seektablePos = 0;
|
||||
drflac_uint32 seektableSize = 0;
|
||||
|
||||
(void)onTell;
|
||||
|
||||
for (;;) {
|
||||
drflac_metadata metadata;
|
||||
drflac_uint8 isLastBlock = 0;
|
||||
|
|
@ -6702,10 +6636,10 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
|
||||
/* Skip to the index point count */
|
||||
pRunningData += 35;
|
||||
|
||||
|
||||
indexCount = pRunningData[0];
|
||||
pRunningData += 1;
|
||||
|
||||
|
||||
bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
|
||||
|
||||
/* Quick validation check. */
|
||||
|
|
@ -6840,7 +6774,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
metadata.data.padding.unused = 0;
|
||||
|
||||
/* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||
} else {
|
||||
onMeta(pUserDataMD, &metadata);
|
||||
|
|
@ -6852,7 +6786,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
{
|
||||
/* Invalid chunk. Just skip over this one. */
|
||||
if (onMeta) {
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
|
||||
}
|
||||
}
|
||||
|
|
@ -6886,7 +6820,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
|
||||
/* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */
|
||||
if (onMeta == NULL && blockSize > 0) {
|
||||
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
isLastBlock = DRFLAC_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -7220,6 +7154,7 @@ typedef struct
|
|||
{
|
||||
drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */
|
||||
drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */
|
||||
drflac_tell_proc onTell; /* The original onTell callback from drflac_open() and family. */
|
||||
void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */
|
||||
drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */
|
||||
drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */
|
||||
|
|
@ -7241,32 +7176,32 @@ static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut,
|
|||
|
||||
static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
|
||||
{
|
||||
if (origin == drflac_seek_origin_start) {
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
if (offset <= 0x7FFFFFFF) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos = offset;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
} else {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos = offset;
|
||||
|
||||
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
|
||||
return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, DRFLAC_SEEK_CUR);
|
||||
}
|
||||
} else {
|
||||
while (offset > 0x7FFFFFFF) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
|
||||
if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos += 0x7FFFFFFF;
|
||||
offset -= 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) { /* <-- Safe cast thanks to the loop above. */
|
||||
if (!oggbs->onSeek(oggbs->pUserData, (int)offset, DRFLAC_SEEK_CUR)) { /* <-- Safe cast thanks to the loop above. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
oggbs->currentBytePos += offset;
|
||||
|
|
@ -7298,7 +7233,7 @@ static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs, drflac_og
|
|||
|
||||
if (header.serialNumber != oggbs->serialNumber) {
|
||||
/* It's not a FLAC page. Skip it. */
|
||||
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
|
||||
if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -7384,7 +7319,7 @@ static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
|
|||
At this point we will have found either the packet or the end of the page. If were at the end of the page we'll
|
||||
want to load the next page and keep searching for the end of the packet.
|
||||
*/
|
||||
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
|
||||
drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, DRFLAC_SEEK_CUR);
|
||||
oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
|
||||
|
||||
if (atEndOfPage) {
|
||||
|
|
@ -7462,8 +7397,8 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
|
||||
/* Seeking is always forward which makes things a lot simpler. */
|
||||
if (origin == drflac_seek_origin_start) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, drflac_seek_origin_start)) {
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -7471,38 +7406,50 @@ static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_see
|
|||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
|
||||
}
|
||||
return drflac__on_seek_ogg(pUserData, offset, DRFLAC_SEEK_CUR);
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
while (bytesSeeked < offset) {
|
||||
int bytesRemainingToSeek = offset - bytesSeeked;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
||||
|
||||
DRFLAC_ASSERT(origin == drflac_seek_origin_current);
|
||||
if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
|
||||
bytesSeeked += bytesRemainingToSeek;
|
||||
(void)bytesSeeked; /* <-- Silence a dead store warning emitted by Clang Static Analyzer. */
|
||||
oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
|
||||
break;
|
||||
}
|
||||
|
||||
while (bytesSeeked < offset) {
|
||||
int bytesRemainingToSeek = offset - bytesSeeked;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
|
||||
/* If we get here it means some of the requested data is contained in the next pages. */
|
||||
if (oggbs->bytesRemainingInPage > 0) {
|
||||
bytesSeeked += (int)oggbs->bytesRemainingInPage;
|
||||
oggbs->bytesRemainingInPage = 0;
|
||||
}
|
||||
|
||||
if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
|
||||
bytesSeeked += bytesRemainingToSeek;
|
||||
(void)bytesSeeked; /* <-- Silence a dead store warning emitted by Clang Static Analyzer. */
|
||||
oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we get here it means some of the requested data is contained in the next pages. */
|
||||
if (oggbs->bytesRemainingInPage > 0) {
|
||||
bytesSeeked += (int)oggbs->bytesRemainingInPage;
|
||||
oggbs->bytesRemainingInPage = 0;
|
||||
}
|
||||
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek > 0);
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
|
||||
/* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */
|
||||
return DRFLAC_FALSE;
|
||||
DRFLAC_ASSERT(bytesRemainingToSeek > 0);
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
|
||||
/* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
/* Seeking to the end is not supported. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_ogg(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
/*
|
||||
Not implemented for Ogg containers because we don't currently track the byte position of the logical bitstream. To support this, we'll need
|
||||
to track the position in drflac__on_read_ogg and drflac__on_seek_ogg.
|
||||
*/
|
||||
(void)pUserData;
|
||||
(void)pCursor;
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
|
||||
static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
|
||||
{
|
||||
|
|
@ -7525,7 +7472,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
|||
runningGranulePosition = 0;
|
||||
for (;;) {
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||
drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
|
||||
drflac_oggbs__seek_physical(oggbs, originalBytePos, DRFLAC_SEEK_SET);
|
||||
return DRFLAC_FALSE; /* Never did find that sample... */
|
||||
}
|
||||
|
||||
|
|
@ -7559,7 +7506,7 @@ static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64
|
|||
a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
|
||||
we find the one containing the target sample.
|
||||
*/
|
||||
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
|
||||
if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, DRFLAC_SEEK_SET)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
|
||||
|
|
@ -7726,7 +7673,7 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||
The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
|
||||
be handling it in a generic way based on the serial number and packet types.
|
||||
*/
|
||||
if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, 2, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -7783,18 +7730,18 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||
}
|
||||
} else {
|
||||
/* Not a FLAC header. Skip it. */
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Not a FLAC header. Seek past the entire page and move on to the next. */
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, bytesRemainingInPage, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, pageBodySize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -7819,18 +7766,19 @@ static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_r
|
|||
}
|
||||
#endif
|
||||
|
||||
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
||||
static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
|
||||
{
|
||||
drflac_bool32 relaxed;
|
||||
drflac_uint8 id[4];
|
||||
|
||||
if (pInit == NULL || onRead == NULL || onSeek == NULL) {
|
||||
if (pInit == NULL || onRead == NULL || onSeek == NULL) { /* <-- onTell is optional. */
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
|
||||
pInit->onRead = onRead;
|
||||
pInit->onSeek = onSeek;
|
||||
pInit->onTell = onTell;
|
||||
pInit->onMeta = onMeta;
|
||||
pInit->container = container;
|
||||
pInit->pUserData = pUserData;
|
||||
|
|
@ -7838,6 +7786,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
|||
|
||||
pInit->bs.onRead = onRead;
|
||||
pInit->bs.onSeek = onSeek;
|
||||
pInit->bs.onTell = onTell;
|
||||
pInit->bs.pUserData = pUserData;
|
||||
drflac__reset_cache(&pInit->bs);
|
||||
|
||||
|
|
@ -7870,7 +7819,7 @@ static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_p
|
|||
headerSize += 10;
|
||||
}
|
||||
|
||||
if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
|
||||
if (!onSeek(pUserData, headerSize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE; /* Failed to seek past the tag. */
|
||||
}
|
||||
pInit->runningFilePos += headerSize;
|
||||
|
|
@ -7922,7 +7871,7 @@ static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
|
|||
}
|
||||
|
||||
|
||||
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac_init_info init;
|
||||
drflac_uint32 allocationSize;
|
||||
|
|
@ -7940,7 +7889,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
/* CPU support first. */
|
||||
drflac__init_cpu_caps();
|
||||
|
||||
if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
|
||||
if (!drflac__init_private(&init, onRead, onSeek, onTell, onMeta, container, pUserData, pUserDataMD)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -7996,6 +7945,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
|
||||
pOggbs->onRead = onRead;
|
||||
pOggbs->onSeek = onSeek;
|
||||
pOggbs->onTell = onTell;
|
||||
pOggbs->pUserData = pUserData;
|
||||
pOggbs->currentBytePos = init.oggFirstBytePos;
|
||||
pOggbs->firstBytePos = init.oggFirstBytePos;
|
||||
|
|
@ -8016,17 +7966,19 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
if (init.hasMetadataBlocks) {
|
||||
drflac_read_proc onReadOverride = onRead;
|
||||
drflac_seek_proc onSeekOverride = onSeek;
|
||||
drflac_tell_proc onTellOverride = onTell;
|
||||
void* pUserDataOverride = pUserData;
|
||||
|
||||
#ifndef DR_FLAC_NO_OGG
|
||||
if (init.container == drflac_container_ogg) {
|
||||
onReadOverride = drflac__on_read_ogg;
|
||||
onSeekOverride = drflac__on_seek_ogg;
|
||||
onTellOverride = drflac__on_tell_ogg;
|
||||
pUserDataOverride = (void*)pOggbs;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
||||
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onTellOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
|
||||
#ifndef DR_FLAC_NO_OGG
|
||||
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
|
||||
#endif
|
||||
|
|
@ -8061,6 +8013,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
/* The Ogg bistream needs to be layered on top of the original bitstream. */
|
||||
pFlac->bs.onRead = drflac__on_read_ogg;
|
||||
pFlac->bs.onSeek = drflac__on_seek_ogg;
|
||||
pFlac->bs.onTell = drflac__on_tell_ogg;
|
||||
pFlac->bs.pUserData = (void*)pInternalOggbs;
|
||||
pFlac->_oggbs = (void*)pInternalOggbs;
|
||||
}
|
||||
|
|
@ -8087,7 +8040,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
|
||||
|
||||
/* Seek to the seektable, then just read directly into our seektable buffer. */
|
||||
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
|
||||
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, DRFLAC_SEEK_SET)) {
|
||||
drflac_uint32 iSeekpoint;
|
||||
|
||||
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
|
||||
|
|
@ -8105,7 +8058,7 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
|
|||
}
|
||||
|
||||
/* We need to seek back to where we were. If this fails it's a critical error. */
|
||||
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
|
||||
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, DRFLAC_SEEK_SET)) {
|
||||
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -8276,7 +8229,7 @@ static drflac_result drflac_result_from_errno(int e)
|
|||
#ifdef ENOSYS
|
||||
case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
#ifdef ENOTEMPTY
|
||||
#if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST /* In AIX, ENOTEMPTY and EEXIST use the same value. */
|
||||
case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
|
|
@ -8727,11 +8680,41 @@ static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t byt
|
|||
|
||||
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
|
||||
{
|
||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
int whence = SEEK_SET;
|
||||
if (origin == DRFLAC_SEEK_CUR) {
|
||||
whence = SEEK_CUR;
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
whence = SEEK_END;
|
||||
}
|
||||
|
||||
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
||||
return fseek((FILE*)pUserData, offset, whence) == 0;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
FILE* pFileStdio = (FILE*)pUserData;
|
||||
drflac_int64 result;
|
||||
|
||||
/* These were all validated at a higher level. */
|
||||
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
result = ftell(pFileStdio);
|
||||
#endif
|
||||
#else
|
||||
result = ftell(pFileStdio);
|
||||
#endif
|
||||
|
||||
*pCursor = result;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
|
|
@ -8742,7 +8725,7 @@ DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocati
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return NULL;
|
||||
|
|
@ -8761,7 +8744,7 @@ DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_all
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return NULL;
|
||||
|
|
@ -8780,7 +8763,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return pFlac;
|
||||
|
|
@ -8799,7 +8782,7 @@ DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, dr
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, drflac__on_tell_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
fclose(pFile);
|
||||
return pFlac;
|
||||
|
|
@ -8834,28 +8817,45 @@ static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t by
|
|||
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
|
||||
{
|
||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||
drflac_int64 newCursor;
|
||||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
|
||||
|
||||
if (offset > (drflac_int64)memoryStream->dataSize) {
|
||||
newCursor = memoryStream->currentReadPos;
|
||||
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
newCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||
} else if (origin == DRFLAC_SEEK_END) {
|
||||
newCursor = (drflac_int64)memoryStream->dataSize;
|
||||
} else {
|
||||
DRFLAC_ASSERT(!"Invalid seek origin");
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
if (origin == drflac_seek_origin_current) {
|
||||
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
|
||||
memoryStream->currentReadPos += offset;
|
||||
} else {
|
||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
||||
}
|
||||
} else {
|
||||
if ((drflac_uint32)offset <= memoryStream->dataSize) {
|
||||
memoryStream->currentReadPos = offset;
|
||||
} else {
|
||||
return DRFLAC_FALSE; /* Trying to seek too far forward. */
|
||||
}
|
||||
newCursor += offset;
|
||||
|
||||
if (newCursor < 0) {
|
||||
return DRFLAC_FALSE; /* Trying to seek prior to the start of the buffer. */
|
||||
}
|
||||
if ((size_t)newCursor > memoryStream->dataSize) {
|
||||
return DRFLAC_FALSE; /* Trying to seek beyond the end of the buffer. */
|
||||
}
|
||||
|
||||
memoryStream->currentReadPos = (size_t)newCursor;
|
||||
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
static drflac_bool32 drflac__on_tell_memory(void* pUserData, drflac_int64* pCursor)
|
||||
{
|
||||
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
|
||||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
*pCursor = (drflac_int64)memoryStream->currentReadPos;
|
||||
return DRFLAC_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -8867,7 +8867,7 @@ DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const
|
|||
memoryStream.data = (const drflac_uint8*)pData;
|
||||
memoryStream.dataSize = dataSize;
|
||||
memoryStream.currentReadPos = 0;
|
||||
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
|
||||
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, &memoryStream, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -8898,7 +8898,7 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
|||
memoryStream.data = (const drflac_uint8*)pData;
|
||||
memoryStream.dataSize = dataSize;
|
||||
memoryStream.currentReadPos = 0;
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, drflac__on_tell_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -8923,22 +8923,22 @@ DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t da
|
|||
|
||||
|
||||
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, NULL, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
return drflac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
DRFLAC_API void drflac_close(drflac* pFlac)
|
||||
|
|
@ -11770,7 +11770,7 @@ DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s32, drflac_int32)
|
|||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
|
||||
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
|
||||
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
|
|
@ -11784,7 +11784,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
|||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -11792,7 +11792,7 @@ DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc on
|
|||
return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||
}
|
||||
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
|
|
@ -11806,7 +11806,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
|||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -11814,7 +11814,7 @@ DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc on
|
|||
return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
|
||||
}
|
||||
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
|
||||
{
|
||||
drflac* pFlac;
|
||||
|
||||
|
|
@ -11828,7 +11828,7 @@ DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, d
|
|||
*totalPCMFrameCountOut = 0;
|
||||
}
|
||||
|
||||
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
|
||||
pFlac = drflac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
|
||||
if (pFlac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -12077,6 +12077,26 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
|||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.13.0 - TBD
|
||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||
- DRFLAC_SEEK_END (new)
|
||||
- API CHANGE: A new seek origin has been added to allow seeking from the end of the file. If you implement your own `onSeek` callback, you should now detect and handle `DRFLAC_SEEK_END`. If seeking to the end is not supported, return `DRFLAC_FALSE`. If you only use `*_open_file()` or `*_open_memory()`, you need not change anything.
|
||||
- API CHANGE: An `onTell` callback has been added to the following functions:
|
||||
- drflac_open()
|
||||
- drflac_open_relaxed()
|
||||
- drflac_open_with_metadata()
|
||||
- drflac_open_with_metadata_relaxed()
|
||||
- drflac_open_and_read_pcm_frames_s32()
|
||||
- drflac_open_and_read_pcm_frames_s16()
|
||||
- drflac_open_and_read_pcm_frames_f32()
|
||||
- Fix compilation for AIX OS.
|
||||
|
||||
v0.12.43 - 2024-12-17
|
||||
- Fix a possible buffer overflow during decoding.
|
||||
- Improve detection of ARM64EC
|
||||
|
||||
v0.12.42 - 2023-11-02
|
||||
- Fix build for ARMv6-M.
|
||||
- Fix a compilation warning with GCC.
|
||||
|
|
|
|||
899
src/external/dr_mp3.h
vendored
899
src/external/dr_mp3.h
vendored
File diff suppressed because it is too large
Load diff
492
src/external/dr_wav.h
vendored
492
src/external/dr_wav.h
vendored
File diff suppressed because it is too large
Load diff
2115
src/external/glfw/src/mappings.h
vendored
2115
src/external/glfw/src/mappings.h
vendored
File diff suppressed because it is too large
Load diff
7
src/external/jar_xm.h
vendored
7
src/external/jar_xm.h
vendored
|
|
@ -232,6 +232,13 @@ uint64_t jar_xm_get_remaining_samples(jar_xm_context_t* ctx);
|
|||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
// Undefine DEBUG to avoid external redefinition warnings/conflicts
|
||||
// This is probably a common definition for
|
||||
// many external build systems' debug configurations
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#if JAR_XM_DEBUG //JAR_XM_DEBUG defined as 0
|
||||
#include <stdio.h>
|
||||
#define DEBUG(fmt, ...) do { \
|
||||
|
|
|
|||
1813
src/external/miniaudio.h
vendored
1813
src/external/miniaudio.h
vendored
File diff suppressed because it is too large
Load diff
989
src/external/rl_gputex.h
vendored
989
src/external/rl_gputex.h
vendored
File diff suppressed because it is too large
Load diff
44
src/external/rprand.h
vendored
44
src/external/rprand.h
vendored
|
|
@ -15,15 +15,15 @@
|
|||
* - Support 64 bits generation
|
||||
*
|
||||
* ADDITIONAL NOTES:
|
||||
* This library implements two pseudo-random number generation algorithms:
|
||||
* This library implements two pseudo-random number generation algorithms:
|
||||
*
|
||||
* - Xoshiro128** : https://prng.di.unimi.it/xoshiro128starstar.c
|
||||
* - SplitMix64 : https://prng.di.unimi.it/splitmix64.c
|
||||
*
|
||||
* SplitMix64 is used to initialize the Xoshiro128** state, from a provided seed
|
||||
*
|
||||
* It's suggested to use SplitMix64 to initialize the state of the generators starting from
|
||||
* a 64-bit seed, as research has shown that initialization must be performed with a generator
|
||||
* It's suggested to use SplitMix64 to initialize the state of the generators starting from
|
||||
* a 64-bit seed, as research has shown that initialization must be performed with a generator
|
||||
* radically different in nature from the one initialized to avoid correlation on similar seeds.
|
||||
*
|
||||
* CONFIGURATION:
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
* Generates the implementation of the library into the included file.
|
||||
* If not defined, the library is in header only mode and can be included in other headers
|
||||
* or source files without problems. But only ONE file should hold the implementation.
|
||||
*
|
||||
*
|
||||
* DEPENDENCIES: none
|
||||
*
|
||||
* VERSIONS HISTORY:
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
#define RPRAND_FREE(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
// Simple log system to avoid RPNG_LOG() calls if required
|
||||
// Simple log system to avoid log calls if required
|
||||
// NOTE: Avoiding those calls, also avoids const strings memory usage
|
||||
#define RPRAND_SHOW_LOG_INFO
|
||||
#if defined(RPNG_SHOW_LOG_INFO)
|
||||
|
|
@ -153,7 +153,7 @@ static uint32_t rprand_state[4] = { // Xoshiro128** state, initializ
|
|||
0x218b21e5,
|
||||
0xaa91febd,
|
||||
0x976414d4
|
||||
};
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module internal functions declaration
|
||||
|
|
@ -190,8 +190,8 @@ int rprand_get_value(int min, int max)
|
|||
int *rprand_load_sequence(unsigned int count, int min, int max)
|
||||
{
|
||||
int *sequence = NULL;
|
||||
|
||||
if (count > (unsigned int)(abs(max - min) + 1))
|
||||
|
||||
if (count > (unsigned int)(abs(max - min) + 1))
|
||||
{
|
||||
RPRAND_LOG("WARNING: Sequence count required is greater than range provided\n");
|
||||
//count = (max - min);
|
||||
|
|
@ -244,26 +244,26 @@ static inline uint32_t rprand_rotate_left(const uint32_t x, int k)
|
|||
}
|
||||
|
||||
// Xoshiro128** generator info:
|
||||
//
|
||||
//
|
||||
// Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
||||
//
|
||||
//
|
||||
// To the extent possible under law, the author has dedicated all copyright
|
||||
// and related and neighboring rights to this software to the public domain
|
||||
// worldwide. This software is distributed without any warranty.
|
||||
//
|
||||
//
|
||||
// See <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
//
|
||||
//
|
||||
// This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid
|
||||
// generators. It has excellent speed, a state size (128 bits) that is
|
||||
// large enough for mild parallelism, and it passes all tests we are aware
|
||||
// of.
|
||||
//
|
||||
//
|
||||
// Note that version 1.0 had mistakenly s[0] instead of s[1] as state
|
||||
// word passed to the scrambler.
|
||||
//
|
||||
//
|
||||
// For generating just single-precision (i.e., 32-bit) floating-point
|
||||
// numbers, xoshiro128+ is even faster.
|
||||
//
|
||||
//
|
||||
// The state must be seeded so that it is not everywhere zero.
|
||||
//
|
||||
uint32_t rprand_xoshiro(void)
|
||||
|
|
@ -275,29 +275,29 @@ uint32_t rprand_xoshiro(void)
|
|||
rprand_state[3] ^= rprand_state[1];
|
||||
rprand_state[1] ^= rprand_state[2];
|
||||
rprand_state[0] ^= rprand_state[3];
|
||||
|
||||
|
||||
rprand_state[2] ^= t;
|
||||
|
||||
|
||||
rprand_state[3] = rprand_rotate_left(rprand_state[3], 11);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// SplitMix64 generator info:
|
||||
//
|
||||
//
|
||||
// Written in 2015 by Sebastiano Vigna (vigna@acm.org)
|
||||
//
|
||||
//
|
||||
// To the extent possible under law, the author has dedicated all copyright
|
||||
// and related and neighboring rights to this software to the public domain
|
||||
// worldwide. This software is distributed without any warranty.
|
||||
//
|
||||
//
|
||||
// See <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
//
|
||||
//
|
||||
//
|
||||
// This is a fixed-increment version of Java 8's SplittableRandom generator
|
||||
// See http://dx.doi.org/10.1145/2714064.2660195 and
|
||||
// http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html
|
||||
//
|
||||
//
|
||||
// It is a very fast generator passing BigCrush, and it can be useful if
|
||||
// for some reason you absolutely want 64 bits of state.
|
||||
uint64_t rprand_splitmix64()
|
||||
|
|
|
|||
9
src/external/sinfl.h
vendored
9
src/external/sinfl.h
vendored
|
|
@ -171,10 +171,11 @@ extern int zsinflate(void *out, int cap, const void *in, int size);
|
|||
|
||||
static int
|
||||
sinfl_bsr(unsigned n) {
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
_BitScanReverse(&n, n);
|
||||
return n;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#ifdef _MSC_VER
|
||||
unsigned long uln = 0;
|
||||
_BitScanReverse(&uln, n);
|
||||
return (int)(uln);
|
||||
#else // defined(__GNUC__) || defined(__clang__) || defined(__TINYC__)
|
||||
return 31 - __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
8
src/external/stb_truetype.h
vendored
8
src/external/stb_truetype.h
vendored
|
|
@ -1863,11 +1863,11 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
|
|||
stbtt_vertex* v = &comp_verts[i];
|
||||
stbtt_vertex_type x,y;
|
||||
x=v->x; y=v->y;
|
||||
v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
|
||||
v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
|
||||
v->x = (stbtt_vertex_type)(mtx[0]*x + mtx[2]*y + mtx[4]*m);
|
||||
v->y = (stbtt_vertex_type)(mtx[1]*x + mtx[3]*y + mtx[5]*n);
|
||||
x=v->cx; y=v->cy;
|
||||
v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
|
||||
v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
|
||||
v->cx = (stbtt_vertex_type)(mtx[0]*x + mtx[2]*y + mtx[4]*m);
|
||||
v->cy = (stbtt_vertex_type)(mtx[1]*x + mtx[3]*y + mtx[5]*n);
|
||||
}
|
||||
// Append vertices.
|
||||
tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,16 @@ typedef struct {
|
|||
EGLConfig config; // Graphic config
|
||||
} PlatformData;
|
||||
|
||||
typedef struct {
|
||||
// Store data for both Hover and Touch events
|
||||
// Used to ignore Hover events which are interpreted as Touch events
|
||||
int32_t pointCount; // Number of touch points active
|
||||
int32_t pointId[MAX_TOUCH_POINTS]; // Point identifiers
|
||||
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
|
||||
|
||||
int32_t hoverPoints[MAX_TOUCH_POINTS]; // Hover Points
|
||||
} TouchRaw;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -246,6 +256,8 @@ static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
|
|||
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
|
||||
};
|
||||
|
||||
static TouchRaw touchRaw = { 0 };
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Internal Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -337,7 +349,7 @@ void MinimizeWindow(void)
|
|||
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||
|
|
@ -431,7 +443,7 @@ int GetMonitorCount(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
|
||||
|
|
@ -801,6 +813,8 @@ int InitPlatform(void)
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) touchRaw.hoverPoints[i] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -859,7 +873,7 @@ static int InitGraphicsDevice(void)
|
|||
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
|
||||
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
||||
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
||||
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
||||
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
|
||||
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
||||
|
|
@ -1269,25 +1283,85 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
}
|
||||
|
||||
// Register touch points count
|
||||
CORE.Input.Touch.pointCount = AMotionEvent_getPointerCount(event);
|
||||
touchRaw.pointCount = AMotionEvent_getPointerCount(event);
|
||||
|
||||
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
// Register touch points id
|
||||
CORE.Input.Touch.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||
touchRaw.pointId[i] = AMotionEvent_getPointerId(event, i);
|
||||
|
||||
// Register touch points position
|
||||
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
||||
touchRaw.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
|
||||
|
||||
// Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height
|
||||
float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;
|
||||
float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;
|
||||
CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
|
||||
CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
|
||||
touchRaw.position[i].x = touchRaw.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
|
||||
touchRaw.position[i].y = touchRaw.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
|
||||
}
|
||||
|
||||
int32_t action = AMotionEvent_getAction(event);
|
||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
if (flags == AMOTION_EVENT_ACTION_HOVER_ENTER)
|
||||
{
|
||||
// The new pointer is hover
|
||||
// So add it to hoverPoints
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||
{
|
||||
if (touchRaw.hoverPoints[i] == -1)
|
||||
{
|
||||
touchRaw.hoverPoints[i] = touchRaw.pointId[pointerIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags == AMOTION_EVENT_ACTION_POINTER_UP) || (flags == AMOTION_EVENT_ACTION_UP) || (flags == AMOTION_EVENT_ACTION_HOVER_EXIT))
|
||||
{
|
||||
// One of the touchpoints is released, remove it from touch point arrays
|
||||
if (flags == AMOTION_EVENT_ACTION_HOVER_EXIT)
|
||||
{
|
||||
// If the touchPoint is hover, remove it from hoverPoints
|
||||
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
|
||||
{
|
||||
if (touchRaw.hoverPoints[i] == touchRaw.pointId[pointerIndex])
|
||||
{
|
||||
touchRaw.hoverPoints[i] = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = pointerIndex; (i < touchRaw.pointCount - 1) && (i < MAX_TOUCH_POINTS - 1); i++)
|
||||
{
|
||||
touchRaw.pointId[i] = touchRaw.pointId[i+1];
|
||||
touchRaw.position[i] = touchRaw.position[i+1];
|
||||
}
|
||||
touchRaw.pointCount--;
|
||||
}
|
||||
|
||||
int pointCount = 0;
|
||||
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
// If the touchPoint is hover, Ignore it
|
||||
bool hover = false;
|
||||
for (int j = 0; j < MAX_TOUCH_POINTS; j++)
|
||||
{
|
||||
// Check if the touchPoint is in hoverPointers
|
||||
if (touchRaw.hoverPoints[j] == touchRaw.pointId[i])
|
||||
{
|
||||
hover = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hover) continue;
|
||||
|
||||
CORE.Input.Touch.pointId[pointCount] = touchRaw.pointId[i];
|
||||
CORE.Input.Touch.position[pointCount] = touchRaw.position[i];
|
||||
pointCount++;
|
||||
}
|
||||
CORE.Input.Touch.pointCount = pointCount;
|
||||
|
||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||
GestureEvent gestureEvent = { 0 };
|
||||
|
|
@ -1312,20 +1386,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
|||
ProcessGestureEvent(gestureEvent);
|
||||
#endif
|
||||
|
||||
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
if (flags == AMOTION_EVENT_ACTION_POINTER_UP || flags == AMOTION_EVENT_ACTION_UP)
|
||||
{
|
||||
// One of the touchpoints is released, remove it from touch point arrays
|
||||
for (int i = pointerIndex; (i < CORE.Input.Touch.pointCount - 1) && (i < MAX_TOUCH_POINTS); i++)
|
||||
{
|
||||
CORE.Input.Touch.pointId[i] = CORE.Input.Touch.pointId[i+1];
|
||||
CORE.Input.Touch.position[i] = CORE.Input.Touch.position[i+1];
|
||||
}
|
||||
|
||||
CORE.Input.Touch.pointCount--;
|
||||
}
|
||||
|
||||
// When all touchpoints are tapped and released really quickly, this event is generated
|
||||
if (flags == AMOTION_EVENT_ACTION_CANCEL) CORE.Input.Touch.pointCount = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* rcore_desktop - Functions to manage window, graphics device and inputs
|
||||
* rcore_desktop_glfw - Functions to manage window, graphics device and inputs
|
||||
*
|
||||
* PLATFORM: DESKTOP: GLFW
|
||||
* - Windows (Win32, Win64)
|
||||
|
|
@ -74,9 +74,14 @@
|
|||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
||||
|
||||
//#define GLFW_EXPOSE_NATIVE_X11 // WARNING: Exposing Xlib.h > X.h results in dup symbols for Font type
|
||||
//#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#define Font X11Font // Hack to fix 'Font' name collision
|
||||
// The definition and references to the X11 Font type will be replaced by 'X11Font'
|
||||
// Works as long as the current file consistently references any X11 Font as X11Font
|
||||
// Since it is never referenced (as of writting), this does not pose an issue
|
||||
#include "GLFW/glfw3native.h" // Required for: glfwGetX11Window()
|
||||
#undef Font // Revert hack and allow normal raylib Font usage
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <unistd.h> // Required for: usleep()
|
||||
|
|
@ -130,9 +135,9 @@ static void CursorEnterCallback(GLFWwindow *window, int enter);
|
|||
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
|
||||
|
||||
// Wrappers used by glfwInitAllocator
|
||||
static void* AllocateWrapper(size_t size, void* user); // GLFW3 GLFWallocatefun, wrapps around RL_MALLOC macro
|
||||
static void* ReallocateWrapper(void* block, size_t size, void* user); // GLFW3 GLFWreallocatefun, wrapps around RL_MALLOC macro
|
||||
static void DeallocateWrapper(void* block, void* user); // GLFW3 GLFWdeallocatefun, wraps around RL_FREE macro
|
||||
static void *AllocateWrapper(size_t size, void *user); // GLFW3 GLFWallocatefun, wrapps around RL_MALLOC macro
|
||||
static void *ReallocateWrapper(void *block, size_t size, void *user); // GLFW3 GLFWreallocatefun, wrapps around RL_MALLOC macro
|
||||
static void DeallocateWrapper(void *block, void *user); // GLFW3 GLFWdeallocatefun, wraps around RL_FREE macro
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
|
|
@ -292,7 +297,7 @@ void MinimizeWindow(void)
|
|||
glfwIconifyWindow(platform.handle);
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
|
||||
|
|
@ -307,6 +312,8 @@ void RestoreWindow(void)
|
|||
// Set window configuration state using flags
|
||||
void SetWindowState(unsigned int flags)
|
||||
{
|
||||
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
|
||||
|
||||
// Check previous state and requested state to apply required changes
|
||||
// NOTE: In most cases the functions already change the flags internally
|
||||
|
||||
|
|
@ -574,7 +581,7 @@ void SetWindowIcons(Image *images, int count)
|
|||
else
|
||||
{
|
||||
int valid = 0;
|
||||
GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));
|
||||
GLFWimage *icons = (GLFWimage *)RL_CALLOC(count, sizeof(GLFWimage));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
|
|
@ -703,6 +710,12 @@ void SetWindowFocused(void)
|
|||
glfwFocusWindow(platform.handle);
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
// Local storage for the window handle returned by glfwGetX11Window
|
||||
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
|
||||
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
|
||||
static XID X11WindowHandle;
|
||||
#endif
|
||||
// Get native window handle
|
||||
void *GetWindowHandle(void)
|
||||
{
|
||||
|
|
@ -711,12 +724,10 @@ void *GetWindowHandle(void)
|
|||
return glfwGetWin32Window(platform.handle);
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
// NOTE: Returned handle is: unsigned long Window (X.h)
|
||||
// typedef unsigned long XID;
|
||||
// typedef XID Window;
|
||||
//unsigned long id = (unsigned long)glfwGetX11Window(platform.handle);
|
||||
//return NULL; // TODO: Find a way to return value... cast to void *?
|
||||
return (void *)platform.handle;
|
||||
// Store the window handle localy and return a pointer to the variable instead.
|
||||
// Reasoning detailed in the declaration of X11WindowHandle
|
||||
X11WindowHandle = glfwGetX11Window(platform.handle);
|
||||
return &X11WindowHandle;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
// NOTE: Returned handle is: (objc_object *)
|
||||
|
|
@ -736,7 +747,7 @@ int GetMonitorCount(void)
|
|||
return monitorCount;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
int index = 0;
|
||||
|
|
@ -1236,7 +1247,7 @@ void PollInputEvents(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Get current axis state
|
||||
// Get current state of axes
|
||||
const float *axes = state.axes;
|
||||
|
||||
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
|
||||
|
|
@ -1244,7 +1255,7 @@ void PollInputEvents(void)
|
|||
CORE.Input.Gamepad.axisState[i][k] = axes[k];
|
||||
}
|
||||
|
||||
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
|
||||
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather as axes)
|
||||
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f)
|
||||
{
|
||||
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1;
|
||||
|
|
@ -1298,17 +1309,17 @@ static void SetDimensionsFromMonitor(GLFWmonitor *monitor)
|
|||
// We need to provide these because GLFWallocator expects function pointers with specific signatures.
|
||||
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch.
|
||||
// https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
|
||||
static void* AllocateWrapper(size_t size, void* user)
|
||||
static void *AllocateWrapper(size_t size, void *user)
|
||||
{
|
||||
(void)user;
|
||||
return RL_MALLOC(size);
|
||||
}
|
||||
static void* ReallocateWrapper(void* block, size_t size, void* user)
|
||||
static void *ReallocateWrapper(void *block, size_t size, void *user)
|
||||
{
|
||||
(void)user;
|
||||
return RL_REALLOC(block, size);
|
||||
}
|
||||
static void DeallocateWrapper(void* block, void* user)
|
||||
static void DeallocateWrapper(void *block, void *user)
|
||||
{
|
||||
(void)user;
|
||||
RL_FREE(block);
|
||||
|
|
@ -1325,6 +1336,7 @@ int InitPlatform(void)
|
|||
.reallocate = ReallocateWrapper,
|
||||
.user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data
|
||||
};
|
||||
|
||||
glfwInitAllocator(&allocator);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
|
@ -1379,6 +1391,12 @@ int InitPlatform(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
|
||||
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
|
||||
|
||||
// HACK: Most of this was written before GLFW_SCALE_FRAMEBUFFER existed and
|
||||
// was enabled by default. Disabling it gets back the old behavior. A
|
||||
// complete fix will require removing a lot of CORE.Window.render
|
||||
// manipulation code.
|
||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
|
||||
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||
{
|
||||
// Resize window content area based on the monitor content scale.
|
||||
|
|
@ -1386,7 +1404,7 @@ int InitPlatform(void)
|
|||
// On platforms like macOS the resolution of the framebuffer is changed independently of the window size.
|
||||
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on
|
||||
#if defined(__APPLE__)
|
||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||
#endif
|
||||
}
|
||||
else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
|
||||
|
|
@ -1600,7 +1618,7 @@ int InitPlatform(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
|
||||
{
|
||||
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
|
||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
|
||||
#if !defined(__APPLE__)
|
||||
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
|
||||
|
||||
|
|
@ -1688,6 +1706,8 @@ int InitPlatform(void)
|
|||
// Retrieve gamepad names
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
|
||||
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -1741,9 +1761,13 @@ static void ErrorCallback(int error, const char *description)
|
|||
}
|
||||
|
||||
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
|
||||
// NOTE: Window resizing not allowed by default
|
||||
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
|
||||
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
// WARNING: On window minimization, callback is called,
|
||||
// but we don't want to change internal screen values, it breaks things
|
||||
if ((width == 0) || (height == 0)) return;
|
||||
|
||||
// Reset viewport and projection matrix for new size
|
||||
SetupViewport(width, height);
|
||||
|
||||
|
|
@ -1753,12 +1777,22 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
|
|||
|
||||
if (IsWindowFullscreen()) return;
|
||||
|
||||
// Set current screen size
|
||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
width = (int)(width/GetWindowScaleDPI().x);
|
||||
height = (int)(height/GetWindowScaleDPI().y);
|
||||
}
|
||||
|
||||
// Set render size
|
||||
CORE.Window.render.width = width;
|
||||
CORE.Window.render.height = height;
|
||||
|
||||
// Set current screen size
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
|
||||
// NOTE: Postprocessing texture is not scaled to new size
|
||||
// WARNING: If using a render texture, it is not scaled to new size
|
||||
}
|
||||
static void WindowPosCallback(GLFWwindow* window, int x, int y)
|
||||
{
|
||||
|
|
@ -1828,8 +1862,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
|
|||
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
|
||||
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
|
||||
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
|
||||
else if(action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
|
||||
else if(action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
|
||||
else if (action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
|
||||
else if (action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
|
||||
|
||||
// WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys
|
||||
if (((key == KEY_CAPS_LOCK) && ((mods & GLFW_MOD_CAPS_LOCK) > 0)) ||
|
||||
|
|
@ -1951,6 +1985,9 @@ static void JoystickCallback(int jid, int event)
|
|||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
|
||||
// we can get a not-NULL terminated string, so, we clean destination and only copy up to -1
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
}
|
||||
else if (event == GLFW_DISCONNECTED)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(PLATFORM_WEB_RGFW)
|
||||
#define RGFW_NO_GL_HEADER
|
||||
#define RGFW_NO_GL_HEADER
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(PLATFORM_WEB_RGFW)
|
||||
|
|
@ -76,14 +76,14 @@ void CloseWindow(void);
|
|||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define Rectangle rectangle_win32
|
||||
#define Rectangle rectangle_win32
|
||||
#define CloseWindow CloseWindow_win32
|
||||
#define ShowCursor __imp_ShowCursor
|
||||
#define _APISETSTRING_
|
||||
|
||||
#undef MAX_PATH
|
||||
#define _APISETSTRING_
|
||||
|
||||
#undef MAX_PATH
|
||||
|
||||
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
|
||||
__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
|
@ -103,8 +103,8 @@ void CloseWindow(void);
|
|||
#undef CloseWindow
|
||||
#undef Rectangle
|
||||
|
||||
#undef MAX_PATH
|
||||
#define MAX_PATH 1025
|
||||
#undef MAX_PATH
|
||||
#define MAX_PATH 1025
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
|
@ -128,7 +128,7 @@ typedef struct {
|
|||
//----------------------------------------------------------------------------------
|
||||
extern CoreData CORE; // Global CORE state context
|
||||
|
||||
static PlatformData platform = { NULL }; // Platform specific
|
||||
static PlatformData platform = { 0 }; // Platform specific
|
||||
|
||||
static bool RGFW_disableCursor = false;
|
||||
|
||||
|
|
@ -175,7 +175,9 @@ static const unsigned short keyMappingRGFW[] = {
|
|||
[RGFW_superL] = KEY_LEFT_SUPER,
|
||||
#ifndef RGFW_MACOS
|
||||
[RGFW_shiftR] = KEY_RIGHT_SHIFT,
|
||||
[RGFW_controlR] = KEY_RIGHT_CONTROL,
|
||||
[RGFW_altR] = KEY_RIGHT_ALT,
|
||||
[RGFW_superR] = KEY_RIGHT_SUPER,
|
||||
#endif
|
||||
[RGFW_space] = KEY_SPACE,
|
||||
|
||||
|
|
@ -264,11 +266,12 @@ bool WindowShouldClose(void)
|
|||
|
||||
// Toggle fullscreen mode
|
||||
void ToggleFullscreen(void)
|
||||
{
|
||||
{
|
||||
if (!CORE.Window.fullscreen)
|
||||
{
|
||||
// Store previous window position (in case we exit fullscreen)
|
||||
CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
|
||||
platform.mon = RGFW_window_getMonitor(platform.window);
|
||||
CORE.Window.fullscreen = true;
|
||||
|
|
@ -281,18 +284,20 @@ void ToggleFullscreen(void)
|
|||
{
|
||||
CORE.Window.fullscreen = false;
|
||||
CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE;
|
||||
|
||||
if (platform.mon.mode.area.w)
|
||||
|
||||
if (platform.mon.mode.area.w)
|
||||
{
|
||||
RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
|
||||
RGFW_monitor_requestMode(monitor, platform.mon.mode, RGFW_monitorScale);
|
||||
|
||||
|
||||
platform.mon.mode.area.w = 0;
|
||||
}
|
||||
|
||||
// we update the window position right away
|
||||
CORE.Window.position = CORE.Window.previousPosition;
|
||||
RGFW_window_setFullscreen(platform.window, 0);
|
||||
RGFW_window_move(platform.window, RGFW_POINT(CORE.Window.position.x, CORE.Window.position.y));
|
||||
RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height));
|
||||
}
|
||||
|
||||
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
|
||||
|
|
@ -303,10 +308,7 @@ void ToggleFullscreen(void)
|
|||
// Toggle borderless windowed mode
|
||||
void ToggleBorderlessWindowed(void)
|
||||
{
|
||||
if (platform.window == NULL)
|
||||
return;
|
||||
|
||||
if (CORE.Window.fullscreen)
|
||||
if (CORE.Window.fullscreen)
|
||||
{
|
||||
CORE.Window.previousPosition = CORE.Window.position;
|
||||
CORE.Window.previousScreen = CORE.Window.screen;
|
||||
|
|
@ -315,7 +317,9 @@ void ToggleBorderlessWindowed(void)
|
|||
|
||||
RGFW_monitor mon = RGFW_window_getMonitor(platform.window);
|
||||
RGFW_window_resize(platform.window, mon.mode.area);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
RGFW_window_setBorder(platform.window, 1);
|
||||
|
||||
CORE.Window.position = CORE.Window.previousPosition;
|
||||
|
|
@ -337,11 +341,10 @@ void MinimizeWindow(void)
|
|||
RGFW_window_minimize(platform.window);
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED))
|
||||
RGFW_window_focus(platform.window);
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
|
||||
|
||||
RGFW_window_restore(platform.window);
|
||||
}
|
||||
|
|
@ -349,6 +352,8 @@ void RestoreWindow(void)
|
|||
// Set window configuration state using flags
|
||||
void SetWindowState(unsigned int flags)
|
||||
{
|
||||
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
|
||||
|
||||
CORE.Window.flags |= flags;
|
||||
|
||||
if (flags & FLAG_VSYNC_HINT)
|
||||
|
|
@ -357,8 +362,7 @@ void SetWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_FULLSCREEN_MODE)
|
||||
{
|
||||
if (!CORE.Window.fullscreen)
|
||||
ToggleFullscreen();
|
||||
if (!CORE.Window.fullscreen) ToggleFullscreen();
|
||||
}
|
||||
if (flags & FLAG_WINDOW_RESIZABLE)
|
||||
{
|
||||
|
|
@ -384,6 +388,8 @@ void SetWindowState(unsigned int flags)
|
|||
if (flags & FLAG_WINDOW_UNFOCUSED)
|
||||
{
|
||||
CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
|
||||
platform.window->_flags &= ~RGFW_windowFocusOnShow;
|
||||
RGFW_window_setFlags(platform.window, platform.window->_flags);
|
||||
}
|
||||
if (flags & FLAG_WINDOW_TOPMOST)
|
||||
{
|
||||
|
|
@ -430,8 +436,7 @@ void ClearWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_FULLSCREEN_MODE)
|
||||
{
|
||||
if (CORE.Window.fullscreen)
|
||||
ToggleFullscreen();
|
||||
if (CORE.Window.fullscreen) ToggleFullscreen();
|
||||
}
|
||||
if (flags & FLAG_WINDOW_RESIZABLE)
|
||||
{
|
||||
|
|
@ -444,25 +449,25 @@ void ClearWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_WINDOW_HIDDEN)
|
||||
{
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED))
|
||||
RGFW_window_focus(platform.window);
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
|
||||
|
||||
RGFW_window_show(platform.window);
|
||||
}
|
||||
if (flags & FLAG_WINDOW_MINIMIZED)
|
||||
{
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED))
|
||||
RGFW_window_focus(platform.window);
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
|
||||
|
||||
RGFW_window_restore(platform.window);
|
||||
}
|
||||
if (flags & FLAG_WINDOW_MAXIMIZED)
|
||||
{
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED))
|
||||
RGFW_window_focus(platform.window);
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
|
||||
|
||||
RGFW_window_restore(platform.window);
|
||||
}
|
||||
if (flags & FLAG_WINDOW_UNFOCUSED)
|
||||
{
|
||||
RGFW_window_setFlags(platform.window, platform.window->_flags | RGFW_windowFocusOnShow);
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
|
||||
}
|
||||
if (flags & FLAG_WINDOW_TOPMOST)
|
||||
|
|
@ -487,8 +492,7 @@ void ClearWindowState(unsigned int flags)
|
|||
}
|
||||
if (flags & FLAG_BORDERLESS_WINDOWED_MODE)
|
||||
{
|
||||
if (CORE.Window.fullscreen)
|
||||
ToggleBorderlessWindowed();
|
||||
if (CORE.Window.fullscreen) ToggleBorderlessWindowed();
|
||||
}
|
||||
if (flags & FLAG_MSAA_4X_HINT)
|
||||
{
|
||||
|
|
@ -502,7 +506,8 @@ void ClearWindowState(unsigned int flags)
|
|||
|
||||
int RGFW_formatToChannels(int format)
|
||||
{
|
||||
switch (format) {
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float)
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float)
|
||||
|
|
@ -547,21 +552,20 @@ void SetWindowIcons(Image *images, int count)
|
|||
if ((images == NULL) || (count <= 0))
|
||||
{
|
||||
RGFW_window_setIcon(platform.window, NULL, RGFW_AREA(0, 0), 0);
|
||||
} {
|
||||
Image* bigIcon = NULL;
|
||||
Image* smallIcon = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Image *bigIcon = NULL;
|
||||
Image *smallIcon = NULL;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (bigIcon == NULL || (images[i].width > bigIcon->width && images[i].height > bigIcon->height))
|
||||
bigIcon = &images[i];
|
||||
if (smallIcon == NULL || (images[i].width < smallIcon->width && images[i].height > smallIcon->height))
|
||||
smallIcon = &images[i];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if ((bigIcon == NULL) || ((images[i].width > bigIcon->width) && (images[i].height > bigIcon->height))) bigIcon = &images[i];
|
||||
if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i];
|
||||
}
|
||||
|
||||
if (smallIcon != NULL)
|
||||
RGFW_window_setIconEx(platform.window, smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow);
|
||||
if (bigIcon != NULL)
|
||||
RGFW_window_setIconEx(platform.window, bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar);
|
||||
|
||||
if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow);
|
||||
if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -581,7 +585,7 @@ void SetWindowPosition(int x, int y)
|
|||
// Set monitor for the current window
|
||||
void SetWindowMonitor(int monitor)
|
||||
{
|
||||
RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]);
|
||||
RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors(NULL)[monitor]);
|
||||
}
|
||||
|
||||
// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
|
||||
|
|
@ -624,7 +628,8 @@ void SetWindowFocused(void)
|
|||
// Get native window handle
|
||||
void *GetWindowHandle(void)
|
||||
{
|
||||
#ifdef RGFW_WEBASM
|
||||
if (platform.window == NULL) return NULL;
|
||||
#ifdef RGFW_WASM
|
||||
return (void *)platform.window->src.ctx;
|
||||
#else
|
||||
return (void *)platform.window->src.window;
|
||||
|
|
@ -637,7 +642,7 @@ int GetMonitorCount(void)
|
|||
#define MAX_MONITORS_SUPPORTED 6
|
||||
|
||||
int count = MAX_MONITORS_SUPPORTED;
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
|
|
@ -651,11 +656,14 @@ int GetMonitorCount(void)
|
|||
return count;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor mon = RGFW_window_getMonitor(platform.window);
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
RGFW_monitor mon = { 0 };
|
||||
|
||||
if (platform.window) mon = RGFW_window_getMonitor(platform.window);
|
||||
else mon = RGFW_getPrimaryMonitor();
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
|
|
@ -668,7 +676,7 @@ int GetCurrentMonitor(void)
|
|||
// Get selected monitor position
|
||||
Vector2 GetMonitorPosition(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y };
|
||||
}
|
||||
|
|
@ -676,7 +684,7 @@ Vector2 GetMonitorPosition(int monitor)
|
|||
// Get selected monitor width (currently used by monitor)
|
||||
int GetMonitorWidth(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return mons[monitor].mode.area.w;
|
||||
}
|
||||
|
|
@ -684,7 +692,7 @@ int GetMonitorWidth(int monitor)
|
|||
// Get selected monitor height (currently used by monitor)
|
||||
int GetMonitorHeight(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return mons[monitor].mode.area.h;
|
||||
}
|
||||
|
|
@ -692,7 +700,7 @@ int GetMonitorHeight(int monitor)
|
|||
// Get selected monitor physical width in millimetres
|
||||
int GetMonitorPhysicalWidth(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return mons[monitor].physW;
|
||||
}
|
||||
|
|
@ -700,7 +708,7 @@ int GetMonitorPhysicalWidth(int monitor)
|
|||
// Get selected monitor physical height in millimetres
|
||||
int GetMonitorPhysicalHeight(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return (int)mons[monitor].physH;
|
||||
}
|
||||
|
|
@ -708,7 +716,7 @@ int GetMonitorPhysicalHeight(int monitor)
|
|||
// Get selected monitor refresh rate
|
||||
int GetMonitorRefreshRate(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return (int)mons[monitor].mode.refreshRate;
|
||||
}
|
||||
|
|
@ -716,7 +724,7 @@ int GetMonitorRefreshRate(int monitor)
|
|||
// Get the human-readable, UTF-8 encoded name of the selected monitor
|
||||
const char *GetMonitorName(int monitor)
|
||||
{
|
||||
RGFW_monitor *mons = RGFW_getMonitors();
|
||||
RGFW_monitor *mons = RGFW_getMonitors(NULL);
|
||||
|
||||
return mons[monitor].name;
|
||||
}
|
||||
|
|
@ -724,15 +732,19 @@ const char *GetMonitorName(int monitor)
|
|||
// Get window position XY on monitor
|
||||
Vector2 GetWindowPosition(void)
|
||||
{
|
||||
if (platform.window == NULL) return (Vector2){ 0.0f, 0.0f };
|
||||
return (Vector2){ (float)platform.window->r.x, (float)platform.window->r.y };
|
||||
}
|
||||
|
||||
// Get window scale DPI factor for current monitor
|
||||
Vector2 GetWindowScaleDPI(void)
|
||||
{
|
||||
RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
|
||||
RGFW_monitor monitor = { 0 };
|
||||
|
||||
return (Vector2){monitor.scaleX, monitor.scaleX};
|
||||
if (platform.window) monitor = RGFW_window_getMonitor(platform.window);
|
||||
else monitor = RGFW_getPrimaryMonitor();
|
||||
|
||||
return (Vector2){ monitor.scaleX, monitor.scaleX };
|
||||
}
|
||||
|
||||
// Set clipboard text content
|
||||
|
|
@ -748,7 +760,6 @@ const char *GetClipboardText(void)
|
|||
return RGFW_readClipboard(NULL);
|
||||
}
|
||||
|
||||
|
||||
#if defined(SUPPORT_CLIPBOARD_IMAGE)
|
||||
#if defined(_WIN32)
|
||||
#define WIN32_CLIPBOARD_IMPLEMENTATION
|
||||
|
|
@ -771,7 +782,7 @@ Image GetClipboardImage(void)
|
|||
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", fileData, dataSize);
|
||||
#else
|
||||
|
|
@ -829,11 +840,7 @@ void SwapScreenBuffer(void)
|
|||
// Get elapsed time measure in seconds since InitTimer()
|
||||
double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
unsigned long long int nanoSeconds = RGFW_getTimeNS();
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
return time;
|
||||
return RGFW_getTime();
|
||||
}
|
||||
|
||||
// Open URL with default system browser (if available)
|
||||
|
|
@ -886,29 +893,30 @@ void SetMouseCursor(int cursor)
|
|||
const char *GetKeyName(int key)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static KeyboardKey ConvertScancodeToKey(u32 keycode);
|
||||
|
||||
int RGFW_gpConvTable[18] = {
|
||||
[RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP,
|
||||
[RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT,
|
||||
[RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN,
|
||||
[RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT,
|
||||
[RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
|
||||
[RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,
|
||||
[RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
|
||||
[RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,
|
||||
[RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT,
|
||||
[RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE,
|
||||
[RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
|
||||
[RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP,
|
||||
[RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT,
|
||||
[RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN,
|
||||
[RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT,
|
||||
[RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB,
|
||||
[RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB,
|
||||
[RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP,
|
||||
[RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT,
|
||||
[RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN,
|
||||
[RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT,
|
||||
[RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
|
||||
[RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,
|
||||
[RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
|
||||
[RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,
|
||||
[RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT,
|
||||
[RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE,
|
||||
[RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
|
||||
[RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP,
|
||||
[RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT,
|
||||
[RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN,
|
||||
[RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT,
|
||||
[RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB,
|
||||
[RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB,
|
||||
};
|
||||
|
||||
// Register all input events
|
||||
|
|
@ -919,7 +927,7 @@ void PollInputEvents(void)
|
|||
// because ProcessGestureEvent() is just called on an event, not every frame
|
||||
UpdateGestures();
|
||||
#endif
|
||||
|
||||
|
||||
// Reset keys/chars pressed registered
|
||||
CORE.Input.Keyboard.keyPressedQueueCount = 0;
|
||||
CORE.Input.Keyboard.charPressedQueueCount = 0;
|
||||
|
|
@ -979,19 +987,25 @@ void PollInputEvents(void)
|
|||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
|
||||
{
|
||||
RGFW_window_eventWait(platform.window, -1); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
||||
CORE.Time.previous = GetTime();
|
||||
}
|
||||
|
||||
while (RGFW_window_checkEvent(platform.window))
|
||||
{
|
||||
RGFW_event *event = &platform.window->event;
|
||||
// All input events can be processed after polling
|
||||
|
||||
switch (event->type)
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case RGFW_quit:
|
||||
if (CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN)
|
||||
event->type = 0;
|
||||
else
|
||||
CORE.Window.shouldClose = true;
|
||||
break;
|
||||
case RGFW_mouseEnter: CORE.Input.Mouse.cursorOnScreen = true; break;
|
||||
case RGFW_mouseLeave: CORE.Input.Mouse.cursorOnScreen = false; break;
|
||||
case RGFW_quit:
|
||||
event->type = 0;
|
||||
CORE.Window.shouldClose = true;
|
||||
return;
|
||||
case RGFW_DND: // Dropped file
|
||||
{
|
||||
for (int i = 0; i < event->droppedFilesCount; i++)
|
||||
|
|
@ -1005,7 +1019,7 @@ void PollInputEvents(void)
|
|||
|
||||
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
|
||||
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
|
||||
|
||||
|
||||
CORE.Window.dropFileCount++;
|
||||
}
|
||||
else if (CORE.Window.dropFileCount < 1024)
|
||||
|
|
@ -1023,12 +1037,38 @@ void PollInputEvents(void)
|
|||
case RGFW_windowResized:
|
||||
{
|
||||
SetupViewport(platform.window->r.w, platform.window->r.h);
|
||||
CORE.Window.screen.width = platform.window->r.w;
|
||||
CORE.Window.screen.height = platform.window->r.h;
|
||||
|
||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
CORE.Window.screen.width = (int)(platform.window->r.w / GetWindowScaleDPI().x);
|
||||
CORE.Window.screen.height = (int)(platform.window->r.h / GetWindowScaleDPI().y);
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.screen.width = platform.window->r.w;
|
||||
CORE.Window.screen.height = platform.window->r.h;
|
||||
}
|
||||
|
||||
CORE.Window.currentFbo.width = platform.window->r.w;
|
||||
CORE.Window.currentFbo.height = platform.window->r.h;
|
||||
CORE.Window.resizedLastFrame = true;
|
||||
} break;
|
||||
case RGFW_windowMaximized:
|
||||
{
|
||||
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // The window was maximized
|
||||
} break;
|
||||
case RGFW_windowMinimized:
|
||||
{
|
||||
CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; // The window was iconified
|
||||
} break;
|
||||
case RGFW_windowRestored:
|
||||
{
|
||||
if (RGFW_window_isMaximized(platform.window))
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // The window was restored
|
||||
if (RGFW_window_isMinimized(platform.window))
|
||||
CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // The window was restored
|
||||
} break;
|
||||
case RGFW_windowMoved:
|
||||
{
|
||||
CORE.Window.position.x = platform.window->r.x;
|
||||
|
|
@ -1079,12 +1119,13 @@ void PollInputEvents(void)
|
|||
{
|
||||
CORE.Input.Mouse.currentWheelMove.y = event->scroll;
|
||||
break;
|
||||
} else CORE.Input.Mouse.currentWheelMove.y = 0;
|
||||
}
|
||||
else CORE.Input.Mouse.currentWheelMove.y = 0;
|
||||
|
||||
int btn = event->button;
|
||||
if (btn == RGFW_mouseLeft) btn = 1;
|
||||
else if (btn == RGFW_mouseRight) btn = 2;
|
||||
else if (btn == RGFW_mouseMiddle) btn = 3;
|
||||
else if (btn == RGFW_mouseMiddle) btn = 3;
|
||||
|
||||
CORE.Input.Mouse.currentButtonState[btn - 1] = 1;
|
||||
CORE.Input.Touch.currentTouchState[btn - 1] = 1;
|
||||
|
|
@ -1097,7 +1138,8 @@ void PollInputEvents(void)
|
|||
{
|
||||
CORE.Input.Mouse.currentWheelMove.y = event->scroll;
|
||||
break;
|
||||
} else CORE.Input.Mouse.currentWheelMove.y = 0;
|
||||
}
|
||||
else CORE.Input.Mouse.currentWheelMove.y = 0;
|
||||
|
||||
int btn = event->button;
|
||||
if (btn == RGFW_mouseLeft) btn = 1;
|
||||
|
|
@ -1127,19 +1169,21 @@ void PollInputEvents(void)
|
|||
touchAction = 2;
|
||||
} break;
|
||||
case RGFW_gamepadConnected:
|
||||
{
|
||||
CORE.Input.Gamepad.ready[platform.window->event.gamepad] = true;
|
||||
CORE.Input.Gamepad.axisCount[platform.window->event.gamepad] = platform.window->event.axisesCount;
|
||||
CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
|
||||
CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
||||
|
||||
strcpy(CORE.Input.Gamepad.name[platform.window->event.gamepad], RGFW_getGamepadName(platform.window, platform.window->event.gamepad));
|
||||
break;
|
||||
} break;
|
||||
case RGFW_gamepadDisconnected:
|
||||
{
|
||||
CORE.Input.Gamepad.ready[platform.window->event.gamepad] = false;
|
||||
break;
|
||||
} break;
|
||||
case RGFW_gamepadButtonPressed:
|
||||
{
|
||||
int button = RGFW_gpConvTable[event->button];
|
||||
int button = RGFW_gpConvTable[event->button];
|
||||
|
||||
if (button >= 0)
|
||||
{
|
||||
|
|
@ -1149,7 +1193,7 @@ void PollInputEvents(void)
|
|||
} break;
|
||||
case RGFW_gamepadButtonReleased:
|
||||
{
|
||||
int button = RGFW_gpConvTable[event->button];
|
||||
int button = RGFW_gpConvTable[event->button];
|
||||
|
||||
CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 0;
|
||||
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
|
|
@ -1157,33 +1201,34 @@ void PollInputEvents(void)
|
|||
case RGFW_gamepadAxisMove:
|
||||
{
|
||||
int axis = -1;
|
||||
float value = 0;
|
||||
|
||||
float value = 0;
|
||||
switch(event->whichAxis)
|
||||
switch(event->whichAxis)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_X] = event->axis[0].x / 100.0f;
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_Y] = event->axis[0].y / 100.0f;
|
||||
} break;
|
||||
case 1:
|
||||
{
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_X] = event->axis[1].x / 100.0f;
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_Y] = event->axis[1].y / 100.0f;
|
||||
} break;
|
||||
case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER;
|
||||
case 3:
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_X] = event->axis[0].x / 100.0f;
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_Y] = event->axis[0].y / 100.0f;
|
||||
} break;
|
||||
case 1:
|
||||
{
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_X] = event->axis[1].x / 100.0f;
|
||||
CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_Y] = event->axis[1].y / 100.0f;
|
||||
} break;
|
||||
case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER;
|
||||
case 3:
|
||||
{
|
||||
if (axis == -1) axis = GAMEPAD_AXIS_RIGHT_TRIGGER;
|
||||
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
|
||||
int pressed = (value > 0.1f);
|
||||
CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = pressed;
|
||||
|
||||
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
|
||||
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
|
||||
int pressed = (value > 0.1f);
|
||||
CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = pressed;
|
||||
|
||||
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
|
||||
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
|
@ -1239,7 +1284,7 @@ int InitPlatform(void)
|
|||
}
|
||||
|
||||
if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0)
|
||||
{
|
||||
{
|
||||
CORE.Window.fullscreen = true;
|
||||
flags |= RGFW_windowedFullscreen;
|
||||
}
|
||||
|
|
@ -1251,44 +1296,51 @@ int InitPlatform(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) flags |= RGFW_windowHide;
|
||||
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) flags |= RGFW_windowMaximize;
|
||||
|
||||
|
||||
// NOTE: Some OpenGL context attributes must be set before window creation
|
||||
|
||||
// Check selection OpenGL version
|
||||
if (rlGetVersion() == RL_OPENGL_21)
|
||||
{
|
||||
if (rlGetVersion() == RL_OPENGL_21)
|
||||
{
|
||||
RGFW_setGLHint(RGFW_glMajor, 2);
|
||||
RGFW_setGLHint(RGFW_glMinor, 1);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_33)
|
||||
{
|
||||
RGFW_setGLHint(RGFW_glCore, 3);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_33)
|
||||
{
|
||||
RGFW_setGLHint(RGFW_glMajor, 3);
|
||||
RGFW_setGLHint(RGFW_glMinor, 3);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_43)
|
||||
{
|
||||
RGFW_setGLHint(RGFW_glCore, 3);
|
||||
}
|
||||
else if (rlGetVersion() == RL_OPENGL_43)
|
||||
{
|
||||
RGFW_setGLHint(RGFW_glMajor, 4);
|
||||
RGFW_setGLHint(RGFW_glMinor, 3);
|
||||
}
|
||||
|
||||
if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLHint(RGFW_glSamples, 4);
|
||||
|
||||
if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) flags |= RGFW_windowFocusOnShow | RGFW_windowFocus;
|
||||
|
||||
platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
|
||||
platform.mon.mode.area.w = 0;
|
||||
|
||||
if (platform.window != NULL)
|
||||
{
|
||||
// NOTE: RGFW's exit key is distinct from raylib's exit key (which can
|
||||
// be set with SetExitKey()) and defaults to Escape
|
||||
platform.window->exitKey = RGFW_keyNULL;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_WEB_RGFW
|
||||
RGFW_area screenSize = RGFW_getScreenSize();
|
||||
CORE.Window.display.width = screenSize.w;
|
||||
CORE.Window.display.height = screenSize.h;
|
||||
#else
|
||||
CORE.Window.display.width = CORE.Window.screen.width;
|
||||
CORE.Window.display.width = CORE.Window.screen.width;
|
||||
CORE.Window.display.height = CORE.Window.screen.height;
|
||||
#endif
|
||||
// TODO: Is this needed by raylib now?
|
||||
// TODO: Is this needed by raylib now?
|
||||
// If so, rcore_desktop_sdl should be updated too
|
||||
//SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
|
||||
//SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
|
||||
|
||||
if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
|
||||
RGFW_window_makeCurrent(platform.window);
|
||||
|
||||
// Check surface and context activation
|
||||
|
|
@ -1338,14 +1390,23 @@ int InitPlatform(void)
|
|||
CORE.Storage.basePath = GetWorkingDirectory();
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifdef RGFW_X11
|
||||
for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
|
||||
{
|
||||
RGFW_registerGamepad(platform.window, i);
|
||||
}
|
||||
#if defined(RGFW_WAYLAND)
|
||||
if (RGFW_useWaylandBool) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully");
|
||||
else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully");
|
||||
#elif defined(RGFW_X11)
|
||||
#if defined(__APPLE__)
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully");
|
||||
#else
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully");
|
||||
#endif
|
||||
#elif defined (RGFW_WINDOWS)
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully");
|
||||
#elif defined(RGFW_WASM)
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully");
|
||||
#elif defined(RGFW_MACOS)
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully");
|
||||
#endif
|
||||
|
||||
TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1359,6 +1420,6 @@ void ClosePlatform(void)
|
|||
static KeyboardKey ConvertScancodeToKey(u32 keycode)
|
||||
{
|
||||
if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0;
|
||||
|
||||
return keyMappingRGFW[keycode];
|
||||
|
||||
return keyMappingRGFW[keycode];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,13 +52,27 @@
|
|||
#ifndef SDL_ENABLE_OLD_NAMES
|
||||
#define SDL_ENABLE_OLD_NAMES // Just in case we're on SDL3, we need some in-between compatibily
|
||||
#endif
|
||||
#include "SDL.h" // SDL base library (window/rendered, input, timing... functionality)
|
||||
// SDL base library (window/rendered, input, timing... functionality)
|
||||
#ifdef USING_SDL3_PROJECT
|
||||
#include "SDL3/SDL.h"
|
||||
#elif USING_SDL2_PROJECT
|
||||
#include "SDL2/SDL.h"
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// It seems it does not need to be included to work
|
||||
//#include "SDL_opengles2.h"
|
||||
#else
|
||||
#include "SDL_opengl.h" // SDL OpenGL functionality (if required, instead of internal renderer)
|
||||
// SDL OpenGL functionality (if required, instead of internal renderer)
|
||||
#ifdef USING_SDL3_PROJECT
|
||||
#include "SDL3/SDL_opengl.h"
|
||||
#elif USING_SDL2_PROJECT
|
||||
#include "SDL2/SDL_opengl.h"
|
||||
#else
|
||||
#include "SDL_opengl.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -238,8 +252,7 @@ static const int CursorsLUT[] = {
|
|||
//SDL_SYSTEM_CURSOR_WAITARROW, // No equivalent implemented on MouseCursor enum on raylib.h
|
||||
};
|
||||
|
||||
|
||||
// SDL3 Migration Layer made to avoid `ifdefs` inside functions when we can.
|
||||
// SDL3 Migration Layer made to avoid 'ifdefs' inside functions when we can.
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
|
||||
// SDL3 Migration:
|
||||
|
|
@ -290,13 +303,13 @@ int SDL_GetNumVideoDisplays(void)
|
|||
int monitorCount = 0;
|
||||
SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount);
|
||||
|
||||
// Safe because If `mem` is NULL, SDL_free does nothing
|
||||
// Safe because If 'mem' is NULL, SDL_free does nothing
|
||||
SDL_free(displays);
|
||||
|
||||
return monitorCount;
|
||||
}
|
||||
|
||||
// SLD3 Migration: To emulate SDL2 this function should return `SDL_DISABLE` or `SDL_ENABLE`
|
||||
// SLD3 Migration: To emulate SDL2 this function should return 'SDL_DISABLE' or 'SDL_ENABLE'
|
||||
// representing the *processing state* of the event before this function makes any changes to it
|
||||
Uint8 SDL_EventState(Uint32 type, int state)
|
||||
{
|
||||
|
|
@ -424,6 +437,8 @@ void ClosePlatform(void); // Close platform
|
|||
|
||||
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode); // Help convert SDL scancodes to raylib key
|
||||
|
||||
static int GetCodepointNextSDL(const char *text, int *codepointSize); // Get next codepoint in a byte sequence and bytes processed
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -508,7 +523,7 @@ void MinimizeWindow(void)
|
|||
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
SDL_RestoreWindow(platform.window);
|
||||
|
|
@ -518,6 +533,8 @@ void RestoreWindow(void)
|
|||
// Set window configuration state using flags
|
||||
void SetWindowState(unsigned int flags)
|
||||
{
|
||||
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
|
||||
|
||||
CORE.Window.flags |= flags;
|
||||
|
||||
if (flags & FLAG_VSYNC_HINT)
|
||||
|
|
@ -563,7 +580,7 @@ void SetWindowState(unsigned int flags)
|
|||
if (flags & FLAG_WINDOW_UNFOCUSED)
|
||||
{
|
||||
// NOTE: To be able to implement this part it seems that we should
|
||||
// do it ourselves, via `Windows.h`, `X11/Xlib.h` or even `Cocoa.h`
|
||||
// do it ourselves, via 'windows.h', 'X11/Xlib.h' or even 'Cocoa.h'
|
||||
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL");
|
||||
}
|
||||
if (flags & FLAG_WINDOW_TOPMOST)
|
||||
|
|
@ -702,70 +719,84 @@ void SetWindowIcon(Image image)
|
|||
switch (image.format)
|
||||
{
|
||||
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
|
||||
{
|
||||
rmask = 0xFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 8, pitch = image.width;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
rmask = 0xFF, gmask = 0xFF00;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
|
||||
{
|
||||
rmask = 0xF800, gmask = 0x07E0;
|
||||
bmask = 0x001F, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
|
||||
rmask = 0x0000FF, gmask = 0x00FF00;
|
||||
bmask = 0xFF0000, amask = 0;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
|
||||
{
|
||||
// WARNING: SDL2 could be using BGR but SDL3 RGB
|
||||
rmask = 0xFF0000, gmask = 0x00FF00;
|
||||
bmask = 0x0000FF, amask = 0;
|
||||
depth = 24, pitch = image.width*3;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
|
||||
{
|
||||
rmask = 0xF800, gmask = 0x07C0;
|
||||
bmask = 0x003E, amask = 0x0001;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
|
||||
{
|
||||
rmask = 0xF000, gmask = 0x0F00;
|
||||
bmask = 0x00F0, amask = 0x000F;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
|
||||
{
|
||||
rmask = 0xFF000000, gmask = 0x00FF0000;
|
||||
bmask = 0x0000FF00, amask = 0x000000FF;
|
||||
depth = 32, pitch = image.width*4;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 32, pitch = image.width*4;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
|
||||
bmask = 0xFFFFFFFF, amask = 0;
|
||||
depth = 96, pitch = image.width*12;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
|
||||
{
|
||||
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
|
||||
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
|
||||
depth = 128, pitch = image.width*16;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0;
|
||||
bmask = 0, amask = 0;
|
||||
depth = 16, pitch = image.width*2;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0xFFFF;
|
||||
bmask = 0xFFFF, amask = 0;
|
||||
depth = 48, pitch = image.width*6;
|
||||
break;
|
||||
} break;
|
||||
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
|
||||
{
|
||||
rmask = 0xFFFF, gmask = 0xFFFF;
|
||||
bmask = 0xFFFF, amask = 0xFFFF;
|
||||
depth = 64, pitch = image.width*8;
|
||||
break;
|
||||
} break;
|
||||
default: return; // Compressed formats are not supported
|
||||
}
|
||||
|
||||
|
|
@ -914,7 +945,7 @@ int GetMonitorCount(void)
|
|||
return monitorCount;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
int currentMonitor = 0;
|
||||
|
|
@ -1137,13 +1168,13 @@ Image GetClipboardImage(void)
|
|||
image = LoadImageFromMemory(imageExtensions[i], fileData, dataSize);
|
||||
if (IsImageValid(image))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", imageExtensions[i]);
|
||||
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsImageValid(image)) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. Error: %s", SDL_GetError());
|
||||
if (!IsImageValid(image)) TRACELOG(LOG_WARNING, "Clipboard: Couldn't get clipboard data. ERROR: %s", SDL_GetError());
|
||||
#endif
|
||||
|
||||
return image;
|
||||
|
|
@ -1349,7 +1380,7 @@ void PollInputEvents(void)
|
|||
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
|
||||
|
||||
// Map touch position to mouse position for convenience
|
||||
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||
if (CORE.Input.Touch.pointCount == 0) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
|
||||
bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
|
||||
|
|
@ -1451,8 +1482,17 @@ void PollInputEvents(void)
|
|||
const int width = event.window.data1;
|
||||
const int height = event.window.data2;
|
||||
SetupViewport(width, height);
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
|
||||
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
|
||||
{
|
||||
CORE.Window.screen.width = (int)(width / GetWindowScaleDPI().x);
|
||||
CORE.Window.screen.height = (int)(height / GetWindowScaleDPI().y);
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE.Window.screen.width = width;
|
||||
CORE.Window.screen.height = height;
|
||||
}
|
||||
CORE.Window.currentFbo.width = width;
|
||||
CORE.Window.currentFbo.height = height;
|
||||
CORE.Window.resizedLastFrame = true;
|
||||
|
|
@ -1576,13 +1616,18 @@ void PollInputEvents(void)
|
|||
{
|
||||
// NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
|
||||
|
||||
int codepointSize = 0;
|
||||
|
||||
// Check if there is space available in the queue
|
||||
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
|
||||
{
|
||||
// Add character (codepoint) to the queue
|
||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = GetCodepointNext(event.text.text, &codepointSize);
|
||||
#if defined(PLATFORM_DESKTOP_SDL3)
|
||||
unsigned int textLen = strlen(event.text.text);
|
||||
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, textLen);
|
||||
#else
|
||||
int codepointSize = 0;
|
||||
int codepoint = GetCodepointNextSDL(event.text.text, &codepointSize);
|
||||
#endif
|
||||
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;
|
||||
CORE.Input.Keyboard.charPressedQueueCount++;
|
||||
}
|
||||
} break;
|
||||
|
|
@ -1661,7 +1706,7 @@ void PollInputEvents(void)
|
|||
{
|
||||
int jid = event.jdevice.which; // Joystick device index
|
||||
|
||||
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
|
||||
if (CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
|
||||
{
|
||||
platform.gamepad[jid] = SDL_GameControllerOpen(jid);
|
||||
platform.gamepadId[jid] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
|
||||
|
|
@ -1672,8 +1717,8 @@ void PollInputEvents(void)
|
|||
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
|
||||
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
|
||||
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
|
||||
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
|
||||
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
|
||||
CORE.Input.Gamepad.name[jid][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1800,7 +1845,7 @@ void PollInputEvents(void)
|
|||
{
|
||||
if (platform.gamepadId[i] == event.jaxis.which)
|
||||
{
|
||||
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
|
||||
// SDL axis value range is -32768 to 32767, we normalize it to raylib's -1.0 to 1.0f range
|
||||
float value = event.jaxis.value/(float)32767;
|
||||
CORE.Input.Gamepad.axisState[i][axis] = value;
|
||||
|
||||
|
|
@ -2068,4 +2113,42 @@ static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
|
|||
|
||||
return KEY_NULL; // No equivalent key in Raylib
|
||||
}
|
||||
// EOF
|
||||
|
||||
// Get next codepoint in a byte sequence and bytes processed
|
||||
static int GetCodepointNextSDL(const char *text, int *codepointSize)
|
||||
{
|
||||
const char *ptr = text;
|
||||
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
||||
*codepointSize = 1;
|
||||
|
||||
// Get current codepoint and bytes processed
|
||||
if (0xf0 == (0xf8 & ptr[0]))
|
||||
{
|
||||
// 4 byte UTF-8 codepoint
|
||||
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
|
||||
*codepointSize = 4;
|
||||
}
|
||||
else if (0xe0 == (0xf0 & ptr[0]))
|
||||
{
|
||||
// 3 byte UTF-8 codepoint */
|
||||
if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
|
||||
*codepointSize = 3;
|
||||
}
|
||||
else if (0xc0 == (0xe0 & ptr[0]))
|
||||
{
|
||||
// 2 byte UTF-8 codepoint
|
||||
if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } // 10xxxxxx checks
|
||||
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
|
||||
*codepointSize = 2;
|
||||
}
|
||||
else if (0x00 == (0x80 & ptr[0]))
|
||||
{
|
||||
// 1 byte UTF-8 codepoint
|
||||
codepoint = ptr[0];
|
||||
*codepointSize = 1;
|
||||
}
|
||||
|
||||
return codepoint;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
||||
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
||||
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
||||
#include <pthread.h> // POSIX threads management (inputs reading)
|
||||
#include <dirent.h> // POSIX directory browsing
|
||||
#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
||||
#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
||||
#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
||||
#include <pthread.h> // POSIX threads management (inputs reading)
|
||||
#include <dirent.h> // POSIX directory browsing
|
||||
|
||||
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
||||
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
||||
|
|
@ -71,6 +71,14 @@
|
|||
#include "EGL/egl.h" // Native platform windowing system interface
|
||||
#include "EGL/eglext.h" // EGL extensions
|
||||
|
||||
// NOTE: DRM cache enables triple buffered DRM caching
|
||||
#if defined(SUPPORT_DRM_CACHE)
|
||||
#include <poll.h> // Required for: drmHandleEvent() poll
|
||||
#include <errno.h> // Required for: EBUSY, EAGAIN
|
||||
|
||||
#define MAX_DRM_CACHED_BUFFERS 3
|
||||
#endif // SUPPORT_DRM_CACHE
|
||||
|
||||
#ifndef EGL_OPENGL_ES3_BIT
|
||||
#define EGL_OPENGL_ES3_BIT 0x40
|
||||
#endif
|
||||
|
|
@ -78,18 +86,16 @@
|
|||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
||||
#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
||||
|
||||
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
||||
#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
||||
|
||||
// So actually the biggest key is KEY_CNT but we only really map the keys up to
|
||||
// KEY_ALS_TOGGLE
|
||||
// Actually biggest key is KEY_CNT but we only really map the keys up to KEY_ALS_TOGGLE
|
||||
#define KEYMAP_SIZE KEY_ALS_TOGGLE
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
// Display data
|
||||
int fd; // File descriptor for /dev/dri/...
|
||||
|
|
@ -124,11 +130,23 @@ typedef struct {
|
|||
|
||||
// Gamepad data
|
||||
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
|
||||
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXIS][2]; // [0] = min, [1] = range value of the axis
|
||||
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXES][2]; // [0] = min, [1] = range value of the axes
|
||||
int gamepadAbsAxisMap[MAX_GAMEPADS][ABS_CNT]; // Maps the axes gamepads from the evdev api to a sequential one
|
||||
int gamepadCount; // The number of gamepads registered
|
||||
} PlatformData;
|
||||
|
||||
#if defined(SUPPORT_DRM_CACHE)
|
||||
typedef struct {
|
||||
struct gbm_bo *bo; // Graphics buffer object
|
||||
uint32_t fbId; // DRM framebuffer ID
|
||||
} FramebufferCache;
|
||||
|
||||
static FramebufferCache fbCache[MAX_DRM_CACHED_BUFFERS] = { 0 };
|
||||
static volatile int fbCacheCount = 0;
|
||||
static volatile bool pendingFlip = false;
|
||||
static bool crtcSet = false;
|
||||
#endif // SUPPORT_DRM_CACHE
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -277,7 +295,7 @@ void MinimizeWindow(void)
|
|||
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||
|
|
@ -371,7 +389,7 @@ int GetMonitorCount(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
|
||||
|
|
@ -551,6 +569,212 @@ void DisableCursor(void)
|
|||
CORE.Input.Mouse.cursorHidden = true;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_DRM_CACHE)
|
||||
|
||||
// Destroy cached framebuffer callback, set by gbm_bo_set_user_data()
|
||||
static void DestroyFrameBufferCallback(struct gbm_bo *bo, void *data)
|
||||
{
|
||||
uint32_t fbId = (uintptr_t)data;
|
||||
|
||||
// Remove from cache
|
||||
for (int i = 0; i < fbCacheCount; i++)
|
||||
{
|
||||
if (fbCache[i].bo == bo)
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DISPLAY: DRM: Framebuffer removed [%u]", (uintptr_t)fbId);
|
||||
drmModeRmFB(platform.fd, fbCache[i].fbId); // Release DRM FB
|
||||
|
||||
// Shift remaining entries
|
||||
for (int j = i; j < fbCacheCount - 1; j++) fbCache[j] = fbCache[j + 1];
|
||||
|
||||
fbCacheCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create or retrieve cached DRM FB for BO
|
||||
static uint32_t GetOrCreateFbForBo(struct gbm_bo *bo)
|
||||
{
|
||||
// Try to find existing cache entry
|
||||
for (int i = 0; i < fbCacheCount; i++)
|
||||
{
|
||||
if (fbCache[i].bo == bo) return fbCache[i].fbId;
|
||||
}
|
||||
|
||||
// Create new entry if cache not full
|
||||
if (fbCacheCount >= MAX_DRM_CACHED_BUFFERS) return 0; // FB cache full
|
||||
|
||||
uint32_t handle = gbm_bo_get_handle(bo).u32;
|
||||
uint32_t stride = gbm_bo_get_stride(bo);
|
||||
uint32_t width = gbm_bo_get_width(bo);
|
||||
uint32_t height = gbm_bo_get_height(bo);
|
||||
|
||||
uint32_t fbId = 0;
|
||||
if (drmModeAddFB(platform.fd, width, height, 24, 32, stride, handle, &fbId)) return 0;
|
||||
|
||||
// Store in cache
|
||||
fbCache[fbCacheCount] = (FramebufferCache){ .bo = bo, .fbId = fbId };
|
||||
fbCacheCount++;
|
||||
|
||||
// Set destroy callback to auto-cleanup
|
||||
gbm_bo_set_user_data(bo, (void *)(uintptr_t)fbId, DestroyFrameBufferCallback);
|
||||
|
||||
TRACELOG(LOG_INFO, "DISPLAY: DRM: Added new buffer object [%u]" , (uintptr_t)fbId);
|
||||
|
||||
return fbId;
|
||||
}
|
||||
|
||||
// Renders a blank frame to allocate initial buffers
|
||||
// TODO: WARNING: Platform layers do not include OpenGL code!
|
||||
void RenderBlankFrame()
|
||||
{
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
eglSwapBuffers(platform.device, platform.surface);
|
||||
glFinish(); // Ensure the buffer is processed
|
||||
}
|
||||
|
||||
// Initialize with first buffer only
|
||||
int InitSwapScreenBuffer()
|
||||
{
|
||||
if (!platform.gbmSurface || (platform.fd < 0))
|
||||
{
|
||||
TRACELOG(LOG_ERROR, "DISPLAY: DRM: Swap buffers can not be initialized");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Render a blank frame to allocate buffers
|
||||
RenderBlankFrame();
|
||||
|
||||
// Get first buffer
|
||||
struct gbm_bo *bo = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
||||
if (!bo)
|
||||
{
|
||||
TRACELOG(LOG_ERROR, "DISPLAY: DRM: Failed to lock initial swap buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create FB for first buffer
|
||||
uint32_t fbId = GetOrCreateFbForBo(bo);
|
||||
if (!fbId)
|
||||
{
|
||||
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initial CRTC setup
|
||||
if (drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, fbId, 0, 0, &platform.connector->connector_id, 1, &platform.connector->modes[platform.modeIndex]))
|
||||
{
|
||||
TRACELOG(LOG_ERROR, "DISPLAY: DRM: Failed to initialize CRTC setup. ERROR: %s", strerror(errno));
|
||||
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Keep first buffer locked until flipped
|
||||
platform.prevBO = bo;
|
||||
crtcSet = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Static page flip handler
|
||||
// NOTE: Called once the drmModePageFlip() finished from the drmHandleEvent() context
|
||||
static void PageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
|
||||
{
|
||||
// Unused inputs
|
||||
(void)fd;
|
||||
(void)frame;
|
||||
(void)sec;
|
||||
(void)usec;
|
||||
|
||||
pendingFlip = false;
|
||||
struct gbm_bo *boToRelease = (struct gbm_bo *)data;
|
||||
|
||||
// Buffers are released after the flip completes (via page_flip_handler), ensuring they're no longer in use
|
||||
// Prevents the GPU from writing to a buffer being scanned out
|
||||
if (boToRelease) gbm_surface_release_buffer(platform.gbmSurface, boToRelease);
|
||||
}
|
||||
|
||||
// Swap implementation with proper caching
|
||||
void SwapScreenBuffer()
|
||||
{
|
||||
if (!crtcSet || !platform.gbmSurface) return;
|
||||
|
||||
static int loopCnt = 0;
|
||||
static int errCnt[5] = {0};
|
||||
loopCnt++;
|
||||
|
||||
// Call this only, if pendingFlip is not set
|
||||
eglSwapBuffers(platform.device, platform.surface);
|
||||
|
||||
// Process pending events non-blocking
|
||||
drmEventContext evctx = {
|
||||
.version = DRM_EVENT_CONTEXT_VERSION,
|
||||
.page_flip_handler = PageFlipHandler
|
||||
};
|
||||
|
||||
struct pollfd pfd = { .fd = platform.fd, .events = POLLIN };
|
||||
|
||||
// Polling for event for 0ms
|
||||
while (poll(&pfd, 1, 0) > 0) drmHandleEvent(platform.fd, &evctx);
|
||||
|
||||
// Skip if previous flip pending
|
||||
if (pendingFlip)
|
||||
{
|
||||
errCnt[0]++; // Skip frame: flip pending
|
||||
return;
|
||||
}
|
||||
|
||||
// Get new front buffer
|
||||
struct gbm_bo *nextBO = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
||||
if (!nextBO) // Failed to lock front buffer
|
||||
{
|
||||
errCnt[1]++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get FB ID (creates new one if needed)
|
||||
uint32_t fbId = GetOrCreateFbForBo(nextBO);
|
||||
if (!fbId)
|
||||
{
|
||||
gbm_surface_release_buffer(platform.gbmSurface, nextBO);
|
||||
errCnt[2]++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt page flip
|
||||
// NOTE: rmModePageFlip() schedules a buffer-flip for the next vblank and then notifies us about it.
|
||||
// It takes a CRTC-id, fb-id and an arbitrary data-pointer and then schedules the page-flip.
|
||||
// This is fully asynchronous and when the page-flip happens, the DRM-fd will become readable and we can call drmHandleEvent().
|
||||
// This will read all vblank/page-flip events and call our modeset_page_flip_event() callback with the data-pointer that we passed to drmModePageFlip().
|
||||
// We simply call modeset_draw_dev() then so the next frame is rendered... returns immediately.
|
||||
if (drmModePageFlip(platform.fd, platform.crtc->crtc_id, fbId, DRM_MODE_PAGE_FLIP_EVENT, platform.prevBO))
|
||||
{
|
||||
if (errno == EBUSY) errCnt[3]++; // Display busy - skip flip
|
||||
else errCnt[4]++; // Page flip failed
|
||||
|
||||
gbm_surface_release_buffer(platform.gbmSurface, nextBO);
|
||||
return;
|
||||
}
|
||||
|
||||
// Success: update state
|
||||
pendingFlip = true;
|
||||
platform.prevBO = nextBO;
|
||||
|
||||
/*
|
||||
// Some benchmarking code
|
||||
if (loopCnt >= 600)
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DRM: Error counters: %d, %d, %d, %d, %d, %d", errCnt[0], errCnt[1], errCnt[2], errCnt[3], errCnt[4], loopCnt);
|
||||
for (int i = 0; i < 5; i++) errCnt[i] = 0;
|
||||
loopCnt = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#else // !SUPPORT_DRM_CACHE
|
||||
|
||||
// Swap back buffer with front buffer (screen drawing)
|
||||
void SwapScreenBuffer(void)
|
||||
{
|
||||
|
|
@ -580,6 +804,7 @@ void SwapScreenBuffer(void)
|
|||
|
||||
platform.prevBO = bo;
|
||||
}
|
||||
#endif // SUPPORT_DRM_CACHE
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition: Misc
|
||||
|
|
@ -735,20 +960,24 @@ int InitPlatform(void)
|
|||
|
||||
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
|
||||
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: Default graphic device DRM opened successfully");
|
||||
#else
|
||||
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: No graphic card set, trying platform-gpu-card");
|
||||
platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: platform-gpu-card opened successfully");
|
||||
|
||||
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open platform-gpu-card, trying card1");
|
||||
platform.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card1 opened successfully");
|
||||
}
|
||||
|
||||
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card1, trying card0");
|
||||
platform.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
|
||||
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card0 opened successfully");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -906,7 +1135,7 @@ int InitPlatform(void)
|
|||
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
|
||||
EGL_ALPHA_SIZE, 8, // ALPHA bit depth (required for transparent framebuffer)
|
||||
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
|
||||
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
|
||||
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
|
||||
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
|
||||
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
|
||||
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
|
||||
|
|
@ -944,7 +1173,7 @@ int InitPlatform(void)
|
|||
|
||||
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
|
||||
|
||||
EGLConfig *configs = RL_CALLOC(numConfigs, sizeof(*configs));
|
||||
EGLConfig *configs = (EGLConfig *)RL_CALLOC(numConfigs, sizeof(*configs));
|
||||
if (!configs)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
|
||||
|
|
@ -1079,9 +1308,21 @@ int InitPlatform(void)
|
|||
CORE.Storage.basePath = GetWorkingDirectory();
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(SUPPORT_DRM_CACHE)
|
||||
if (InitSwapScreenBuffer() == 0)
|
||||
{
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized successfully");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized failed");
|
||||
return -1;
|
||||
}
|
||||
#else // !SUPPORT_DRM_CACHE
|
||||
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized successfully");
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close platform
|
||||
|
|
@ -1370,7 +1611,7 @@ static void InitEvdevInput(void)
|
|||
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
|
||||
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
|
||||
{
|
||||
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
||||
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
|
||||
ConfigureEvdevDevice(path); // Configure the device if appropriate
|
||||
}
|
||||
}
|
||||
|
|
@ -1399,7 +1640,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
int fd = open(device, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "DRM: Failed to open input device: %s", device);
|
||||
TRACELOG(LOG_WARNING, "SYSTEM: Failed to open input device: %s", device);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1456,7 +1697,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
// matter if we support them
|
||||
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
|
||||
|
||||
// If any of the common joystick axis is present, we assume it's a gamepad
|
||||
// If any of the common joystick axes are present, we assume it's a gamepad
|
||||
else
|
||||
{
|
||||
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
|
||||
|
|
@ -1542,7 +1783,7 @@ static void ConfigureEvdevDevice(char *device)
|
|||
if (absAxisCount > 0)
|
||||
{
|
||||
// TODO / NOTE
|
||||
// So gamepad axis (as in the actual linux joydev.c) are just simply enumerated
|
||||
// So gamepad axes (as in the actual linux joydev.c) are just simply enumerated
|
||||
// and (at least for some input drivers like xpat) it's convention to use
|
||||
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the
|
||||
// shoulder buttons
|
||||
|
|
@ -1677,7 +1918,7 @@ static void PollGamepadEvents(void)
|
|||
|
||||
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: Axis: %2i Value: %i", i, axisRaylib, event.value);
|
||||
|
||||
if (axisRaylib < MAX_GAMEPAD_AXIS)
|
||||
if (axisRaylib < MAX_GAMEPAD_AXES)
|
||||
{
|
||||
int min = platform.gamepadAbsAxisRange[i][event.code][0];
|
||||
int range = platform.gamepadAbsAxisRange[i][event.code][1];
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void MinimizeWindow(void)
|
|||
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
|
||||
}
|
||||
|
||||
// Set window state: not minimized/maximized
|
||||
// Restore window from being minimized/maximized
|
||||
void RestoreWindow(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
|
||||
|
|
@ -208,7 +208,7 @@ int GetMonitorCount(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Get number of monitors
|
||||
// Get current monitor where window is placed
|
||||
int GetCurrentMonitor(void)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue