Merge branch 'raysan5:master' into master

This commit is contained in:
Luiz Pestana 2022-09-24 10:17:20 -03:00 committed by GitHub
commit e30fa528a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1936 additions and 1213 deletions

View File

@ -6,7 +6,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| name | raylib version | language | license | repo |
|:------------------:|:---------------:|:---------:|:----------:|-----------------------------------------------------------|
| raylib | **4.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | https://github.com/raysan5/raylib |
| raylib | **4.2** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | https://github.com/raysan5/raylib |
| raylib-boo | 3.7 | [Boo](http://boo-language.github.io/)| MIT | https://github.com/Rabios/raylib-boo |
| Raylib-cs | **4.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | https://github.com/ChrisDill/Raylib-cs |
| Raylib-CsLo | **4.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | https://github.com/NotNotTech/Raylib-CsLo |
@ -15,7 +15,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| dart-raylib | **4.0** | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib |
| bindbc-raylib3 | **4.0** | [D](https://dlang.org/) | BSL-1.0 | https://github.com/o3o/bindbc-raylib3 |
| dray | **4.0** | [D](https://dlang.org/) | Apache-2.0 | https://github.com/xdrie/dray |
| raylib-d | **4.0** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d |
| raylib-d | **4.2** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d |
| dlang_raylib | **4.0** | [D](https://dlang.org) | MPL-2.0 |https://github.com/rc-05/dlang_raylib |
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex |
| raylib-factor | **4.0** | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
@ -29,7 +29,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib-j | **4.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib | https://github.com/CreedVI/Raylib-J |
| raylib.jl | **4.2** | [Julia](https://julialang.org/) | Zlib | https://github.com/irishgreencitrus/raylib.jl |
| kaylib | 3.7 | [Kotlin/native](https://kotlinlang.org) | ? | https://github.com/electronstudio/kaylib |
| raylib-lua | **4.0** | [Lua](http://www.lua.org/) | ISC | https://github.com/TSnake41/raylib-lua |
| raylib-lua | **4.2** | [Lua](http://www.lua.org/) | ISC | https://github.com/TSnake41/raylib-lua |
| raylua | **4.0** | [Lua](http://www.lua.org/) | MIT | https://github.com/Rabios/raylua |
| nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib |
| NimraylibNow! | 4.2 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now |
@ -39,7 +39,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib_odin_bindings | 4.0-dev | [Odin](https://odin-lang.org/) | MIT | https://github.com/Deathbat2190/raylib_odin_bindings |
| raylib-odin | **4.0** | [Odin](https://odin-lang.org/) | BSD-3Clause | https://github.com/odin-lang/Odin/tree/master/vendor/raylib |
| raylib-ocaml | **4.0** | [OCaml](https://ocaml.org/) | MIT | https://github.com/tjammer/raylib-ocaml |
| Ray4Laz | **4.2** | [Pascal](https://en.wikipedia.org/wiki/Pascal_(programming_language))| Zlib | https://github.com/GuvaCode/Ray4Laz |
| Ray4Laz | **4.2** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/GuvaCode/Ray4Laz |
| Raylib.4.0.Pascal | **4.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)| Zlib | https://github.com/sysrpl/Raylib.4.0.Pascal |
| pyraylib | 3.7 | [Python](https://www.python.org/) | Zlib | https://github.com/Ho011/pyraylib |
| raylib-python-cffi | **4.2** | [Python](https://www.python.org/) | EPL-2.0 | https://github.com/electronstudio/raylib-python-cffi |
@ -54,7 +54,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib-smallBasic | 4.1-dev | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib |
| raylib.v | **4.2** | [V](https://vlang.io/) | Zlib | https://github.com/irishgreencitrus/raylib.v |
| raylib-wren | **4.0** | [Wren](http://wren.io/) | ISC | https://github.com/TSnake41/raylib-wren |
| raylib-zig | **4.0** | [Zig](https://ziglang.org/) | MIT | https://github.com/Not-Nik/raylib-zig |
| raylib-zig | **4.2** | [Zig](https://ziglang.org/) | MIT | https://github.com/Not-Nik/raylib-zig |
| raylib.zig | **4.2** | [Zig](https://ziglang.org/) | MIT | https://github.com/ryupold/raylib.zig |
| hare-raylib | auto | [Hare](https://harelang.org/) | Zlib | https://git.sr.ht/~evantj/hare-raylib |

View File

@ -1,6 +1,6 @@
/*******************************************************************************************
*
* raylib [cpre] example - loading thread
* raylib [core] example - loading thread
*
* NOTE: This example requires linking with pthreads library on MinGW,
* it can be accomplished passing -static parameter to compiler

View File

@ -57,7 +57,7 @@ int main(void)
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 4.0f, 2.0f));
// Load basic lighting shader
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base_lighting.vs", GLSL_VERSION),
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/lighting.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/lighting.fs", GLSL_VERSION));
// Get some required shader locations
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");

View File

@ -63,7 +63,7 @@ int main(void)
modelC.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
// Load shader and set up some uniforms
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/base_lighting.vs", GLSL_VERSION),
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/lighting.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/fog.fs", GLSL_VERSION));
shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");

View File

@ -57,6 +57,10 @@ int main(void)
bool showFontAtlas = false;
int codepointSize = 0;
int codepoint = 0;
char *ptr = text;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -66,6 +70,20 @@ int main(void)
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE)) showFontAtlas = !showFontAtlas;
// Testing code: getting next and previous codepoints on provided text
if (IsKeyPressed(KEY_RIGHT))
{
// Get next codepoint in string and move pointer
codepoint = GetCodepointNext(ptr, &codepointSize);
ptr += codepointSize;
}
else if (IsKeyPressed(KEY_LEFT))
{
// Get previous codepoint in string and move pointer
codepoint = GetCodepointPrevious(ptr, &codepointSize);
ptr -= codepointSize;
}
//----------------------------------------------------------------------------------
// Draw

View File

@ -42,7 +42,7 @@ int main(void)
// Draw on the image with a few image draw methods
ImageDrawPixel(&parrots, 10, 10, RAYWHITE);
ImageDrawCircle(&parrots, 10, 10, 5, RAYWHITE);
ImageDrawCircleLines(&parrots, 10, 10, 5, RAYWHITE);
ImageDrawRectangle(&parrots, 5, 20, 10, 10, RAYWHITE);
UnloadImage(cat); // Unload image from RAM

View File

@ -5,12 +5,13 @@ project(example)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Dependencies
find_package(raylib 4.2.0 QUIET) # QUIET or REQUIRED
set(RAYLIB_VERSION 4.2.0)
find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED
if (NOT raylib_FOUND) # If there's none, fetch and build raylib
include(FetchContent)
FetchContent_Declare(
raylib
URL https://github.com/raysan5/raylib/archive/refs/tags/4.0.0.tar.gz
URL https://github.com/raysan5/raylib/archive/refs/tags/${RAYLIB_VERSION}.tar.gz
)
FetchContent_GetProperties(raylib)
if (NOT raylib_POPULATED) # Have we downloaded raylib yet?

170
src/external/glad.h vendored
View File

@ -1,9 +1,9 @@
/**
* Loader generated by glad 2.0.0-beta on Sun Oct 17 18:39:09 2021
* Loader generated by glad 2.0.0-beta on Sun Sep 18 18:12:12 2022
*
* Generator: C/C++
* Specification: gl
* Extensions: 110
* Extensions: 116
*
* APIs:
* - gl:core=4.3
@ -12,16 +12,16 @@
* - ALIAS = False
* - DEBUG = False
* - HEADER_ONLY = True
* - LOADER = True
* - LOADER = False
* - MX = False
* - MX_GLOBAL = False
* - ON_DEMAND = False
*
* Commandline:
* --api='gl:core=4.3' --extensions='GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_map_buffer_range,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_pipeline_statistics_query,GL_ARB_query_buffer_object,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_texture_lod,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_spirv_extensions,GL_ARB_tessellation_shader,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_compression,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_rg,GL_ARB_texture_storage,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_OES_compressed_paletted_texture,GL_OES_fixed_point' c --header-only --loader
* --api='gl:core=4.3' --extensions='GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_map_buffer_range,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_pipeline_statistics_query,GL_ARB_query_buffer_object,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_texture_lod,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_spirv_extensions,GL_ARB_tessellation_shader,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_compression,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_rg,GL_ARB_texture_storage,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_EXT_draw_instanced,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_mirror_clamp,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_OES_compressed_paletted_texture,GL_OES_fixed_point' c --header-only
*
* Online:
* http://glad.sh/#api=gl%3Acore%3D4.3&generator=c&options=HEADER_ONLY%2CLOADER
* http://glad.sh/#api=gl%3Acore%3D4.3&generator=c&options=HEADER_ONLY
*
*/
@ -54,7 +54,6 @@
#define GLAD_GL
#define GLAD_OPTION_GL_HEADER_ONLY
#define GLAD_OPTION_GL_LOADER
#ifdef __cplusplus
extern "C" {
@ -381,11 +380,25 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_COMPRESSED_RGBA 0x84EE
#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
@ -395,6 +408,20 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
#define GL_COMPRESSED_SRGB 0x8C48
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
#define GL_COMPRESSED_SRGB8_ETC2 0x9275
#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
@ -1067,6 +1094,7 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#define GL_MAX_TEXTURE_SIZE 0x0D33
#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
@ -1113,7 +1141,10 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_MIPMAP 0x8293
#define GL_MIRRORED_REPEAT 0x8370
#define GL_MIRRORED_REPEAT_ARB 0x8370
#define GL_MIRROR_CLAMP_EXT 0x8742
#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
#define GL_MULTISAMPLE 0x809D
#define GL_MULTISAMPLE_ARB 0x809D
#define GL_MULTISAMPLE_BIT_ARB 0x20000000
@ -1749,6 +1780,7 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_TEXTURE_MAX_LEVEL 0x813D
#define GL_TEXTURE_MAX_LOD 0x813B
#define GL_TEXTURE_MIN_FILTER 0x2801
@ -2159,6 +2191,20 @@ typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
@ -2241,14 +2287,21 @@ typedef unsigned short int khronos_uint16_t;
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
@ -2294,113 +2347,70 @@ typedef enum {
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
typedef void GLvoid;
typedef khronos_int8_t GLbyte;
typedef khronos_uint8_t GLubyte;
typedef khronos_int16_t GLshort;
typedef khronos_uint16_t GLushort;
typedef int GLint;
typedef unsigned int GLuint;
typedef khronos_int32_t GLclampx;
typedef int GLsizei;
typedef khronos_float_t GLfloat;
typedef khronos_float_t GLclampf;
typedef double GLdouble;
typedef double GLclampd;
typedef void *GLeglClientBufferEXT;
typedef void *GLeglImageOES;
typedef char GLchar;
typedef char GLcharARB;
#ifdef __APPLE__
typedef void *GLhandleARB;
#else
typedef unsigned int GLhandleARB;
#endif
typedef khronos_uint16_t GLhalf;
typedef khronos_uint16_t GLhalfARB;
typedef khronos_int32_t GLfixed;
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
typedef khronos_intptr_t GLintptr;
#else
typedef khronos_intptr_t GLintptr;
#endif
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
typedef khronos_intptr_t GLintptrARB;
#else
typedef khronos_intptr_t GLintptrARB;
#endif
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
typedef khronos_ssize_t GLsizeiptr;
#else
typedef khronos_ssize_t GLsizeiptr;
#endif
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
typedef khronos_ssize_t GLsizeiptrARB;
#else
typedef khronos_ssize_t GLsizeiptrARB;
#endif
typedef khronos_int64_t GLint64;
typedef khronos_int64_t GLint64EXT;
typedef khronos_uint64_t GLuint64;
typedef khronos_uint64_t GLuint64EXT;
typedef struct __GLsync *GLsync;
struct _cl_context;
struct _cl_event;
typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
typedef unsigned short GLhalfNV;
typedef GLintptr GLvdpauSurfaceNV;
typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
#define GL_VERSION_1_0 1
GLAD_API_CALL int GLAD_GL_VERSION_1_0;
#define GL_VERSION_1_1 1
@ -2593,8 +2603,6 @@ GLAD_API_CALL int GLAD_GL_ARB_texture_border_clamp;
GLAD_API_CALL int GLAD_GL_ARB_texture_buffer_object_rgb32;
#define GL_ARB_texture_compression 1
GLAD_API_CALL int GLAD_GL_ARB_texture_compression;
#define GL_EXT_texture_compression_s3tc 1
GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
#define GL_ARB_texture_cube_map 1
GLAD_API_CALL int GLAD_GL_ARB_texture_cube_map;
#define GL_ARB_texture_cube_map_array 1
@ -2641,6 +2649,8 @@ GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object;
GLAD_API_CALL int GLAD_GL_ARB_vertex_program;
#define GL_ARB_vertex_shader 1
GLAD_API_CALL int GLAD_GL_ARB_vertex_shader;
#define GL_EXT_draw_instanced 1
GLAD_API_CALL int GLAD_GL_EXT_draw_instanced;
#define GL_EXT_fog_coord 1
GLAD_API_CALL int GLAD_GL_EXT_fog_coord;
#define GL_EXT_framebuffer_blit 1
@ -2651,6 +2661,16 @@ GLAD_API_CALL int GLAD_GL_EXT_framebuffer_multisample;
GLAD_API_CALL int GLAD_GL_EXT_framebuffer_object;
#define GL_EXT_framebuffer_sRGB 1
GLAD_API_CALL int GLAD_GL_EXT_framebuffer_sRGB;
#define GL_EXT_texture_compression_s3tc 1
GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
#define GL_EXT_texture_filter_anisotropic 1
GLAD_API_CALL int GLAD_GL_EXT_texture_filter_anisotropic;
#define GL_EXT_texture_mirror_clamp 1
GLAD_API_CALL int GLAD_GL_EXT_texture_mirror_clamp;
#define GL_KHR_texture_compression_astc_hdr 1
GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_hdr;
#define GL_KHR_texture_compression_astc_ldr 1
GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
#define GL_OES_compressed_paletted_texture 1
GLAD_API_CALL int GLAD_GL_OES_compressed_paletted_texture;
#define GL_OES_fixed_point 1
@ -2848,6 +2868,7 @@ typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum mode, const void
typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDARBPROC)(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDEXTPROC)(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf);
typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs);
typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSARBPROC)(GLsizei n, const GLenum * bufs);
@ -2859,6 +2880,7 @@ typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDARBPROC)(GLenum mode, GLsi
typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance);
typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum mode, GLuint id);
@ -4045,6 +4067,8 @@ GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB;
#define glDrawArraysInstancedARB glad_glDrawArraysInstancedARB
GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance;
#define glDrawArraysInstancedBaseInstance glad_glDrawArraysInstancedBaseInstance
GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT;
#define glDrawArraysInstancedEXT glad_glDrawArraysInstancedEXT
GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
#define glDrawBuffer glad_glDrawBuffer
GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
@ -4067,6 +4091,8 @@ GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstan
#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance;
#define glDrawElementsInstancedBaseVertexBaseInstance glad_glDrawElementsInstancedBaseVertexBaseInstance
GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT;
#define glDrawElementsInstancedEXT glad_glDrawElementsInstancedEXT
GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
#define glDrawRangeElements glad_glDrawRangeElements
GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
@ -5682,12 +5708,6 @@ GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
#ifdef GLAD_GL
GLAD_API_CALL int gladLoaderLoadGL(void);
GLAD_API_CALL void gladLoaderUnloadGL(void);
#endif
#ifdef __cplusplus
}
@ -5813,7 +5833,6 @@ int GLAD_GL_ARB_tessellation_shader = 0;
int GLAD_GL_ARB_texture_border_clamp = 0;
int GLAD_GL_ARB_texture_buffer_object_rgb32 = 0;
int GLAD_GL_ARB_texture_compression = 0;
int GLAD_GL_EXT_texture_compression_s3tc = 0;
int GLAD_GL_ARB_texture_cube_map = 0;
int GLAD_GL_ARB_texture_cube_map_array = 0;
int GLAD_GL_ARB_texture_env_add = 0;
@ -5837,11 +5856,17 @@ int GLAD_GL_ARB_vertex_attrib_binding = 0;
int GLAD_GL_ARB_vertex_buffer_object = 0;
int GLAD_GL_ARB_vertex_program = 0;
int GLAD_GL_ARB_vertex_shader = 0;
int GLAD_GL_EXT_draw_instanced = 0;
int GLAD_GL_EXT_fog_coord = 0;
int GLAD_GL_EXT_framebuffer_blit = 0;
int GLAD_GL_EXT_framebuffer_multisample = 0;
int GLAD_GL_EXT_framebuffer_object = 0;
int GLAD_GL_EXT_framebuffer_sRGB = 0;
int GLAD_GL_EXT_texture_compression_s3tc = 0;
int GLAD_GL_EXT_texture_filter_anisotropic = 0;
int GLAD_GL_EXT_texture_mirror_clamp = 0;
int GLAD_GL_KHR_texture_compression_astc_hdr = 0;
int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
int GLAD_GL_OES_compressed_paletted_texture = 0;
int GLAD_GL_OES_fixed_point = 0;
@ -6038,6 +6063,7 @@ PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect = NULL;
PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB = NULL;
PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance = NULL;
PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT = NULL;
PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
PFNGLDRAWBUFFERSARBPROC glad_glDrawBuffersARB = NULL;
@ -6049,6 +6075,7 @@ PFNGLDRAWELEMENTSINSTANCEDARBPROC glad_glDrawElementsInstancedARB = NULL;
PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance = NULL;
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance = NULL;
PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT = NULL;
PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback = NULL;
@ -8122,6 +8149,11 @@ static void glad_gl_load_GL_ARB_vertex_shader( GLADuserptrloadfunc load, void* u
glad_glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB");
glad_glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB");
}
static void glad_gl_load_GL_EXT_draw_instanced( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_EXT_draw_instanced) return;
glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
}
static void glad_gl_load_GL_EXT_fog_coord( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_EXT_fog_coord) return;
glad_glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC) load(userptr, "glFogCoordPointerEXT");
@ -8451,8 +8483,7 @@ static int glad_gl_find_extensions_gl( int version) {
GLAD_GL_ARB_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_border_clamp");
GLAD_GL_ARB_texture_buffer_object_rgb32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_buffer_object_rgb32");
GLAD_GL_ARB_texture_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_compression");
GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc");
GLAD_GL_ARB_texture_cube_map = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_cube_map");
GLAD_GL_ARB_texture_cube_map = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_cube_map");
GLAD_GL_ARB_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_cube_map_array");
GLAD_GL_ARB_texture_env_add = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_env_add");
GLAD_GL_ARB_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_filter_anisotropic");
@ -8475,11 +8506,17 @@ static int glad_gl_find_extensions_gl( int version) {
GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_buffer_object");
GLAD_GL_ARB_vertex_program = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_program");
GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_shader");
GLAD_GL_EXT_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_instanced");
GLAD_GL_EXT_fog_coord = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_fog_coord");
GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit");
GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample");
GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object");
GLAD_GL_EXT_framebuffer_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_sRGB");
GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc");
GLAD_GL_EXT_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_anisotropic");
GLAD_GL_EXT_texture_mirror_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_mirror_clamp");
GLAD_GL_KHR_texture_compression_astc_hdr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_hdr");
GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_ldr");
GLAD_GL_OES_compressed_paletted_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_paletted_texture");
GLAD_GL_OES_fixed_point = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fixed_point");
@ -8615,6 +8652,7 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr);
glad_gl_load_GL_ARB_vertex_program(load, userptr);
glad_gl_load_GL_ARB_vertex_shader(load, userptr);
glad_gl_load_GL_EXT_draw_instanced(load, userptr);
glad_gl_load_GL_EXT_fog_coord(load, userptr);
glad_gl_load_GL_EXT_framebuffer_blit(load, userptr);
glad_gl_load_GL_EXT_framebuffer_multisample(load, userptr);
@ -8632,6 +8670,10 @@ int gladLoadGL( GLADloadfunc load) {
}
#ifdef __cplusplus
}
#endif

818
src/external/rl_gputex.h vendored Normal file
View File

@ -0,0 +1,818 @@
/**********************************************************************************************
*
* rl_gputex - GPU compressed textures loading and saving
*
* DESCRIPTION:
*
* Load GPU compressed image data from image files provided as memory data arrays,
* data is loaded compressed, ready to be loaded into GPU.
*
* Note that some file formats (DDS, PVR, KTX) also support uncompressed data storage.
* In those cases data is loaded uncompressed and format is returned.
*
* TODO:
* - Implement raylib function: rlGetGlTextureFormats(), required by rl_save_ktx_to_memory()
* - Review rl_load_ktx_from_memory() to support KTX v2.2 specs
*
* CONFIGURATION:
*
* #define RL_GPUTEX_SUPPORT_DDS
* #define RL_GPUTEX_SUPPORT_PKM
* #define RL_GPUTEX_SUPPORT_KTX
* #define RL_GPUTEX_SUPPORT_PVR
* #define RL_GPUTEX_SUPPORT_ASTC
* Define desired file formats to be supported
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2022 Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RL_GPUTEX_H
#define RL_GPUTEX_H
#ifndef RLAPI
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
#endif
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
#if defined(__cplusplus)
extern "C" { // Prevents name mangling of functions
#endif
// Load image data from memory data files
RLAPI void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips);
RLAPI void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips);
RLAPI void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips);
RLAPI void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips);
RLAPI void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips);
RLAPI int rl_save_ktx_to_memory(const char *fileName, void *data, int width, int height, int format, int mipmaps); // Save image data as KTX file
#if defined(__cplusplus)
}
#endif
#endif // RL_GPUTEX_H
/***********************************************************************************
*
* RL_GPUTEX IMPLEMENTATION
*
************************************************************************************/
#if defined(RL_GPUTEX_IMPLEMENTATION)
// Simple log system to avoid RPNG_LOG() calls if required
// NOTE: Avoiding those calls, also avoids const strings memory usage
#define RL_GPUTEX_SHOW_LOG_INFO
#if defined(RL_GPUTEX_SHOW_LOG_INFO) && !defined(LOG)
#define LOG(...) printf(__VA_ARGS__)
#else
#define LOG(...)
#endif
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
// Get pixel data size in bytes for certain pixel format
static int get_pixel_data_size(int width, int height, int format);
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
#if defined(RL_GPUTEX_SUPPORT_DDS)
// Loading DDS from memory image data (compressed or uncompressed)
void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
void *image_data = NULL; // Image data pointer
int image_pixel_size = 0; // Image pixel size
unsigned char *file_data_ptr = (unsigned char *)file_data;
// Required extension:
// GL_EXT_texture_compression_s3tc
// Supported tokens (defined by extensions)
// GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
// GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
// GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
// DDS Pixel Format
typedef struct {
unsigned int size;
unsigned int flags;
unsigned int fourcc;
unsigned int rgb_bit_count;
unsigned int r_bit_mask;
unsigned int g_bit_mask;
unsigned int b_bit_mask;
unsigned int a_bit_mask;
} dds_pixel_format;
// DDS Header (124 bytes)
typedef struct {
unsigned int size;
unsigned int flags;
unsigned int height;
unsigned int width;
unsigned int pitch_or_linear_size;
unsigned int depth;
unsigned int mipmap_count;
unsigned int reserved1[11];
dds_pixel_format ddspf;
unsigned int caps;
unsigned int caps2;
unsigned int caps3;
unsigned int caps4;
unsigned int reserved2;
} dds_header;
if (file_data_ptr != NULL)
{
// Verify the type of file
unsigned char *dds_header_id = file_data_ptr;
file_data_ptr += 4;
if ((dds_header_id[0] != 'D') || (dds_header_id[1] != 'D') || (dds_header_id[2] != 'S') || (dds_header_id[3] != ' '))
{
LOG("WARNING: IMAGE: DDS file data not valid");
}
else
{
dds_header *header = (dds_header *)file_data_ptr;
file_data_ptr += sizeof(dds_header); // Skip header
*width = header->width;
*height = header->height;
image_pixel_size = header->width*header->height;
if (header->mipmap_count == 0) *mips = 1; // Parameter not used
else *mips = header->mipmap_count;
if (header->ddspf.rgb_bit_count == 16) // 16bit mode, no compressed
{
if (header->ddspf.flags == 0x40) // No alpha channel
{
int data_size = image_pixel_size*sizeof(unsigned short);
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
*format = PIXELFORMAT_UNCOMPRESSED_R5G6B5;
}
else if (header->ddspf.flags == 0x41) // With alpha channel
{
if (header->ddspf.a_bit_mask == 0x8000) // 1bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
unsigned char alpha = 0;
// NOTE: Data comes as A1R5G5B5, it must be reordered to R5G5B5A1
for (int i = 0; i < image_pixel_size; i++)
{
alpha = ((unsigned short *)image_data)[i] >> 15;
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 1;
((unsigned short *)image_data)[i] += alpha;
}
*format = PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
}
else if (header->ddspf.a_bit_mask == 0xf000) // 4bit alpha
{
int data_size = image_pixel_size*sizeof(unsigned short);
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
unsigned char alpha = 0;
// NOTE: Data comes as A4R4G4B4, it must be reordered R4G4B4A4
for (int i = 0; i < image_pixel_size; i++)
{
alpha = ((unsigned short *)image_data)[i] >> 12;
((unsigned short *)image_data)[i] = ((unsigned short *)image_data)[i] << 4;
((unsigned short *)image_data)[i] += alpha;
}
*format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
}
}
}
else if (header->ddspf.flags == 0x40 && header->ddspf.rgb_bit_count == 24) // DDS_RGB, no compressed
{
int data_size = image_pixel_size*3*sizeof(unsigned char);
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
*format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
}
else if (header->ddspf.flags == 0x41 && header->ddspf.rgb_bit_count == 32) // DDS_RGBA, no compressed
{
int data_size = image_pixel_size*4*sizeof(unsigned char);
image_data = RL_MALLOC(data_size);
memcpy(image_data, file_data_ptr, data_size);
unsigned char blue = 0;
// NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment)
// DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
// So, we must realign B8G8R8A8 to R8G8B8A8
for (int i = 0; i < image_pixel_size*4; i += 4)
{
blue = ((unsigned char *)image_data)[i];
((unsigned char *)image_data)[i] = ((unsigned char *)image_data)[i + 2];
((unsigned char *)image_data)[i + 2] = blue;
}
*format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
}
else if (((header->ddspf.flags == 0x04) || (header->ddspf.flags == 0x05)) && (header->ddspf.fourcc > 0)) // Compressed
{
int data_size = 0;
// Calculate data size, including all mipmaps
if (header->mipmap_count > 1) data_size = header->pitch_or_linear_size*2;
else data_size = header->pitch_or_linear_size;
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
memcpy(image_data, file_data_ptr, data_size);
switch (header->ddspf.fourcc)
{
case FOURCC_DXT1:
{
if (header->ddspf.flags == 0x04) *format = PIXELFORMAT_COMPRESSED_DXT1_RGB;
else *format = PIXELFORMAT_COMPRESSED_DXT1_RGBA;
} break;
case FOURCC_DXT3: *format = PIXELFORMAT_COMPRESSED_DXT3_RGBA; break;
case FOURCC_DXT5: *format = PIXELFORMAT_COMPRESSED_DXT5_RGBA; break;
default: break;
}
}
}
}
return image_data;
}
#endif
#if defined(RL_GPUTEX_SUPPORT_PKM)
// Loading PKM image data (ETC1/ETC2 compression)
// NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
// PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
void *image_data = NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
// Required extensions:
// GL_OES_compressed_ETC1_RGB8_texture (ETC1) (OpenGL ES 2.0)
// GL_ARB_ES3_compatibility (ETC2/EAC) (OpenGL ES 3.0)
// Supported tokens (defined by extensions)
// GL_ETC1_RGB8_OES 0x8D64
// GL_COMPRESSED_RGB8_ETC2 0x9274
// GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
// PKM file (ETC1) Header (16 bytes)
typedef struct {
char id[4]; // "PKM "
char version[2]; // "10" or "20"
unsigned short format; // Data format (big-endian) (Check list below)
unsigned short width; // Texture width (big-endian) (orig_width rounded to multiple of 4)
unsigned short height; // Texture height (big-endian) (orig_height rounded to multiple of 4)
unsigned short orig_width; // Original width (big-endian)
unsigned short orig_height; // Original height (big-endian)
} pkm_header;
// Formats list
// version 10: format: 0=ETC1_RGB, [1=ETC1_RGBA, 2=ETC1_RGB_MIP, 3=ETC1_RGBA_MIP] (not used)
// version 20: format: 0=ETC1_RGB, 1=ETC2_RGB, 2=ETC2_RGBA_OLD, 3=ETC2_RGBA, 4=ETC2_RGBA1, 5=ETC2_R, 6=ETC2_RG, 7=ETC2_SIGNED_R, 8=ETC2_SIGNED_R
// NOTE: The extended width and height are the widths rounded up to a multiple of 4.
// NOTE: ETC is always 4bit per pixel (64 bit for each 4x4 block of pixels)
if (file_data_ptr != NULL)
{
pkm_header *header = (pkm_header *)file_data_ptr;
if ((header->id[0] != 'P') || (header->id[1] != 'K') || (header->id[2] != 'M') || (header->id[3] != ' '))
{
LOG("WARNING: IMAGE: PKM file data not valid");
}
else
{
file_data_ptr += sizeof(pkm_header); // Skip header
// NOTE: format, width and height come as big-endian, data must be swapped to little-endian
header->format = ((header->format & 0x00FF) << 8) | ((header->format & 0xFF00) >> 8);
header->width = ((header->width & 0x00FF) << 8) | ((header->width & 0xFF00) >> 8);
header->height = ((header->height & 0x00FF) << 8) | ((header->height & 0xFF00) >> 8);
*width = header->width;
*height = header->height;
*mips = 1;
int bpp = 4;
if (header->format == 3) bpp = 8;
int data_size = (*width)*(*height)*bpp/8; // Total data size in bytes
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
memcpy(image_data, file_data_ptr, data_size);
if (header->format == 0) *format = PIXELFORMAT_COMPRESSED_ETC1_RGB;
else if (header->format == 1) *format = PIXELFORMAT_COMPRESSED_ETC2_RGB;
else if (header->format == 3) *format = PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
}
}
return image_data;
}
#endif
#if defined(RL_GPUTEX_SUPPORT_KTX)
// Load KTX compressed image data (ETC1/ETC2 compression)
// TODO: Review KTX loading, many things changed!
void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
void *image_data = NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
// Required extensions:
// GL_OES_compressed_ETC1_RGB8_texture (ETC1)
// GL_ARB_ES3_compatibility (ETC2/EAC)
// Supported tokens (defined by extensions)
// GL_ETC1_RGB8_OES 0x8D64
// GL_COMPRESSED_RGB8_ETC2 0x9274
// GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
// KTX file Header (64 bytes)
// v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
// v2.0 - http://github.khronos.org/KTX-Specification/
// KTX 1.1 Header
// TODO: Support KTX 2.2 specs!
typedef struct {
char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n"
unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
unsigned int gl_type; // For compressed textures, glType must equal 0
unsigned int gl_type_size; // For compressed texture data, usually 1
unsigned int gl_format; // For compressed textures is 0
unsigned int gl_internal_format; // Compressed internal format
unsigned int gl_base_internal_format; // Same as glFormat (RGB, RGBA, ALPHA...)
unsigned int width; // Texture image width in pixels
unsigned int height; // Texture image height in pixels
unsigned int depth; // For 2D textures is 0
unsigned int elements; // Number of array elements, usually 0
unsigned int faces; // Cubemap faces, for no-cubemap = 1
unsigned int mipmap_levels; // Non-mipmapped textures = 1
unsigned int key_value_data_size; // Used to encode any arbitrary data...
} ktx_header;
// NOTE: Before start of every mipmap data block, we have: unsigned int data_size
if (file_data_ptr != NULL)
{
ktx_header *header = (ktx_header *)file_data_ptr;
if ((header->id[1] != 'K') || (header->id[2] != 'T') || (header->id[3] != 'X') ||
(header->id[4] != ' ') || (header->id[5] != '1') || (header->id[6] != '1'))
{
LOG("WARNING: IMAGE: KTX file data not valid");
}
else
{
file_data_ptr += sizeof(ktx_header); // Move file data pointer
*width = header->width;
*height = header->height;
*mips = header->mipmap_levels;
file_data_ptr += header->key_value_data_size; // Skip value data size
int data_size = ((int *)file_data_ptr)[0];
file_data_ptr += sizeof(int);
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
memcpy(image_data, file_data_ptr, data_size);
if (header->gl_internal_format == 0x8D64) *format = PIXELFORMAT_COMPRESSED_ETC1_RGB;
else if (header->gl_internal_format == 0x9274) *format = PIXELFORMAT_COMPRESSED_ETC2_RGB;
else if (header->gl_internal_format == 0x9278) *format = PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
// TODO: Support uncompressed data formats? Right now it returns format = 0!
}
}
return image_data;
}
// Save image data as KTX file
// NOTE: By default KTX 1.1 spec is used, 2.0 is still on draft (01Oct2018)
// TODO: Review KTX saving, many things changed!
int rl_save_ktx(const char *file_name, void *data, int width, int height, int format, int mipmaps)
{
// KTX file Header (64 bytes)
// v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
// v2.0 - http://github.khronos.org/KTX-Specification/ - Final specs by 2021-04-18
typedef struct {
char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n" // KTX 2.0: "«KTX 22»\r\n\x1A\n"
unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
unsigned int gl_type; // For compressed textures, glType must equal 0
unsigned int gl_type_size; // For compressed texture data, usually 1
unsigned int gl_format; // For compressed textures is 0
unsigned int gl_internal_format; // Compressed internal format
unsigned int gl_base_internal_format; // Same as glFormat (RGB, RGBA, ALPHA...) // KTX 2.0: UInt32 vkFormat
unsigned int width; // Texture image width in pixels
unsigned int height; // Texture image height in pixels
unsigned int depth; // For 2D textures is 0
unsigned int elements; // Number of array elements, usually 0
unsigned int faces; // Cubemap faces, for no-cubemap = 1
unsigned int mipmap_levels; // Non-mipmapped textures = 1
unsigned int key_value_data_size; // Used to encode any arbitrary data... // KTX 2.0: UInt32 levelOrder - ordering of the mipmap levels, usually 0
// KTX 2.0: UInt32 supercompressionScheme - 0 (None), 1 (Crunch CRN), 2 (Zlib DEFLATE)...
// KTX 2.0 defines additional header elements...
} ktx_header;
// Calculate file data_size required
int data_size = sizeof(ktx_header);
for (int i = 0, width = width, height = height; i < mipmaps; i++)
{
data_size += get_pixel_data_size(width, height, format);
width /= 2; height /= 2;
}
unsigned char *file_data = RL_CALLOC(data_size, 1);
unsigned char *file_data_ptr = file_data;
ktx_header header = { 0 };
// KTX identifier (v1.1)
//unsigned char id[12] = { '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' };
//unsigned char id[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
const char ktx_identifier[12] = { 0xAB, 'K', 'T', 'X', ' ', '1', '1', 0xBB, '\r', '\n', 0x1A, '\n' };
// Get the image header
memcpy(header.id, ktx_identifier, 12); // KTX 1.1 signature
header.endianness = 0;
header.gl_type = 0; // Obtained from format
header.gl_type_size = 1;
header.gl_format = 0; // Obtained from format
header.gl_internal_format = 0; // Obtained from format
header.gl_base_internal_format = 0;
header.width = width;
header.height = height;
header.depth = 0;
header.elements = 0;
header.faces = 1;
header.mipmap_levels = mipmaps; // If it was 0, it means mipmaps should be generated on loading (not for compressed formats)
header.key_value_data_size = 0; // No extra data after the header
rlGetGlTextureFormats(format, &header.gl_internal_format, &header.gl_format, &header.gl_type); // rlgl module function
header.gl_base_internal_format = header.gl_format; // KTX 1.1 only
// NOTE: We can save into a .ktx all PixelFormats supported by raylib, including compressed formats like DXT, ETC or ASTC
if (header.gl_format == -1) LOG("WARNING: IMAGE: GL format not supported for KTX export (%i)", header.gl_format);
else
{
memcpy(file_data_ptr, &header, sizeof(ktx_header));
file_data_ptr += sizeof(ktx_header);
int temp_width = width;
int temp_height = height;
int data_offset = 0;
// Save all mipmaps data
for (int i = 0; i < mipmaps; i++)
{
unsigned int data_size = get_pixel_data_size(temp_width, temp_height, format);
memcpy(file_data_ptr, &data_size, sizeof(unsigned int));
memcpy(file_data_ptr + 4, (unsigned char *)data + data_offset, data_size);
temp_width /= 2;
temp_height /= 2;
data_offset += data_size;
file_data_ptr += (4 + data_size);
}
}
// Save file data to file
int success = false;
FILE *file = fopen(file_name, "wb");
if (file != NULL)
{
unsigned int count = (unsigned int)fwrite(file_data, sizeof(unsigned char), data_size, file);
if (count == 0) LOG("WARNING: FILEIO: [%s] Failed to write file", file_name);
else if (count != data_size) LOG("WARNING: FILEIO: [%s] File partially written", file_name);
else LOG("INFO: FILEIO: [%s] File saved successfully", file_name);
int result = fclose(file);
if (result == 0) success = true;
}
else LOG("WARNING: FILEIO: [%s] Failed to open file", file_name);
RL_FREE(file_data); // Free file data buffer
// If all data has been written correctly to file, success = 1
return success;
}
#endif
#if defined(RL_GPUTEX_SUPPORT_PVR)
// Loading PVR image data (uncompressed or PVRT compression)
// NOTE: PVR v2 not supported, use PVR v3 instead
void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
void *image_data = NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
// Required extension:
// GL_IMG_texture_compression_pvrtc
// Supported tokens (defined by extensions)
// GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
// GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
#if 0 // Not used...
// PVR file v2 Header (52 bytes)
typedef struct {
unsigned int headerLength;
unsigned int height;
unsigned int width;
unsigned int numMipmaps;
unsigned int flags;
unsigned int dataLength;
unsigned int bpp;
unsigned int bitmaskRed;
unsigned int bitmaskGreen;
unsigned int bitmaskBlue;
unsigned int bitmaskAlpha;
unsigned int pvrTag;
unsigned int numSurfs;
} PVRHeaderV2;
#endif
// PVR file v3 Header (52 bytes)
// NOTE: After it could be metadata (15 bytes?)
typedef struct {
char id[4];
unsigned int flags;
unsigned char channels[4]; // pixelFormat high part
unsigned char channel_depth[4]; // pixelFormat low part
unsigned int color_space;
unsigned int channel_type;
unsigned int height;
unsigned int width;
unsigned int depth;
unsigned int num_surfaces;
unsigned int num_faces;
unsigned int num_mipmaps;
unsigned int metadata_size;
} pvr_header;
#if 0 // Not used...
// Metadata (usually 15 bytes)
typedef struct {
unsigned int devFOURCC;
unsigned int key;
unsigned int data_size; // Not used?
unsigned char *data; // Not used?
} PVRMetadata;
#endif
if (file_data_ptr != NULL)
{
// Check PVR image version
unsigned char pvr_version = file_data_ptr[0];
// Load different PVR data formats
if (pvr_version == 0x50)
{
pvr_header *header = (pvr_header *)file_data_ptr;
if ((header->id[0] != 'P') || (header->id[1] != 'V') || (header->id[2] != 'R') || (header->id[3] != 3))
{
LOG("WARNING: IMAGE: PVR file data not valid");
}
else
{
file_data_ptr += sizeof(pvr_header); // Skip header
*width = header->width;
*height = header->height;
*mips = header->num_mipmaps;
// Check data format
if (((header->channels[0] == 'l') && (header->channels[1] == 0)) && (header->channel_depth[0] == 8)) *format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
else if (((header->channels[0] == 'l') && (header->channels[1] == 'a')) && ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8))) *format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
else if ((header->channels[0] == 'r') && (header->channels[1] == 'g') && (header->channels[2] == 'b'))
{
if (header->channels[3] == 'a')
{
if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 5) && (header->channel_depth[2] == 5) && (header->channel_depth[3] == 1)) *format = PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
else if ((header->channel_depth[0] == 4) && (header->channel_depth[1] == 4) && (header->channel_depth[2] == 4) && (header->channel_depth[3] == 4)) *format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8) && (header->channel_depth[3] == 8)) *format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
}
else if (header->channels[3] == 0)
{
if ((header->channel_depth[0] == 5) && (header->channel_depth[1] == 6) && (header->channel_depth[2] == 5)) *format = PIXELFORMAT_UNCOMPRESSED_R5G6B5;
else if ((header->channel_depth[0] == 8) && (header->channel_depth[1] == 8) && (header->channel_depth[2] == 8)) *format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
}
}
else if (header->channels[0] == 2) *format = PIXELFORMAT_COMPRESSED_PVRT_RGB;
else if (header->channels[0] == 3) *format = PIXELFORMAT_COMPRESSED_PVRT_RGBA;
file_data_ptr += header->metadata_size; // Skip meta data header
// Calculate data size (depends on format)
int bpp = 0;
switch (*format)
{
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
case PIXELFORMAT_COMPRESSED_PVRT_RGB:
case PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
default: break;
}
int data_size = (*width)*(*height)*bpp/8; // Total data size in bytes
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
memcpy(image_data, file_data_ptr, data_size);
}
}
else if (pvr_version == 52) LOG("INFO: IMAGE: PVRv2 format not supported, update your files to PVRv3");
}
return image_data;
}
#endif
#if defined(RL_GPUTEX_SUPPORT_ASTC)
// Load ASTC compressed image data (ASTC compression)
void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file_size, int *width, int *height, int *format, int *mips)
{
void *image_data = NULL; // Image data pointer
unsigned char *file_data_ptr = (unsigned char *)file_data;
// Required extensions:
// GL_KHR_texture_compression_astc_hdr
// GL_KHR_texture_compression_astc_ldr
// Supported tokens (defined by extensions)
// GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93b0
// GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7
// ASTC file Header (16 bytes)
typedef struct {
unsigned char id[4]; // Signature: 0x13 0xAB 0xA1 0x5C
unsigned char blockX; // Block X dimensions
unsigned char blockY; // Block Y dimensions
unsigned char blockZ; // Block Z dimensions (1 for 2D images)
unsigned char width[3]; // void *width in pixels (24bit value)
unsigned char height[3]; // void *height in pixels (24bit value)
unsigned char length[3]; // void *Z-size (1 for 2D images)
} astc_header;
if (file_data_ptr != NULL)
{
astc_header *header = (astc_header *)file_data_ptr;
if ((header->id[3] != 0x5c) || (header->id[2] != 0xa1) || (header->id[1] != 0xab) || (header->id[0] != 0x13))
{
LOG("WARNING: IMAGE: ASTC file data not valid");
}
else
{
file_data_ptr += sizeof(astc_header); // Skip header
// NOTE: Assuming Little Endian (could it be wrong?)
*width = 0x00000000 | ((int)header->width[2] << 16) | ((int)header->width[1] << 8) | ((int)header->width[0]);
*height = 0x00000000 | ((int)header->height[2] << 16) | ((int)header->height[1] << 8) | ((int)header->height[0]);
*mips = 1; // NOTE: ASTC format only contains one mipmap level
// NOTE: Each block is always stored in 128bit so we can calculate the bpp
int bpp = 128/(header->blockX*header->blockY);
// NOTE: Currently we only support 2 blocks configurations: 4x4 and 8x8
if ((bpp == 8) || (bpp == 2))
{
int data_size = (*width)*(*height)*bpp/8; // Data size in bytes
image_data = RL_MALLOC(data_size*sizeof(unsigned char));
memcpy(image_data, file_data_ptr, data_size);
if (bpp == 8) *format = PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA;
else if (bpp == 2) *format = PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA;
}
else LOG("WARNING: IMAGE: ASTC block size configuration not supported");
}
}
return image_data;
}
#endif
//----------------------------------------------------------------------------------
// Module Internal Functions Definition
//----------------------------------------------------------------------------------
// Get pixel data size in bytes for certain pixel format
static int get_pixel_data_size(int width, int height, int format)
{
int data_size = 0; // Size in bytes
int bpp = 0; // Bits per pixel
switch (format)
{
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
case PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
case PIXELFORMAT_COMPRESSED_DXT1_RGB:
case PIXELFORMAT_COMPRESSED_DXT1_RGBA:
case PIXELFORMAT_COMPRESSED_ETC1_RGB:
case PIXELFORMAT_COMPRESSED_ETC2_RGB:
case PIXELFORMAT_COMPRESSED_PVRT_RGB:
case PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
case PIXELFORMAT_COMPRESSED_DXT3_RGBA:
case PIXELFORMAT_COMPRESSED_DXT5_RGBA:
case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
default: break;
}
data_size = width*height*bpp/8; // Total data size in bytes
// Most compressed formats works on 4x4 blocks,
// if texture is smaller, minimum dataSize is 8 or 16
if ((width < 4) && (height < 4))
{
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) data_size = 8;
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) data_size = 16;
}
return data_size;
}
#endif // RL_GPUTEX_IMPLEMENTATION

428
src/external/stb_perlin.h vendored Normal file
View File

@ -0,0 +1,428 @@
// stb_perlin.h - v0.5 - perlin noise
// public domain single-file C implementation by Sean Barrett
//
// LICENSE
//
// See end of file.
//
//
// to create the implementation,
// #define STB_PERLIN_IMPLEMENTATION
// in *one* C/CPP file that includes this file.
//
//
// Documentation:
//
// float stb_perlin_noise3( float x,
// float y,
// float z,
// int x_wrap=0,
// int y_wrap=0,
// int z_wrap=0)
//
// This function computes a random value at the coordinate (x,y,z).
// Adjacent random values are continuous but the noise fluctuates
// its randomness with period 1, i.e. takes on wholly unrelated values
// at integer points. Specifically, this implements Ken Perlin's
// revised noise function from 2002.
//
// The "wrap" parameters can be used to create wraparound noise that
// wraps at powers of two. The numbers MUST be powers of two. Specify
// 0 to mean "don't care". (The noise always wraps every 256 due
// details of the implementation, even if you ask for larger or no
// wrapping.)
//
// float stb_perlin_noise3_seed( float x,
// float y,
// float z,
// int x_wrap=0,
// int y_wrap=0,
// int z_wrap=0,
// int seed)
//
// As above, but 'seed' selects from multiple different variations of the
// noise function. The current implementation only uses the bottom 8 bits
// of 'seed', but possibly in the future more bits will be used.
//
//
// Fractal Noise:
//
// Three common fractal noise functions are included, which produce
// a wide variety of nice effects depending on the parameters
// provided. Note that each function will call stb_perlin_noise3
// 'octaves' times, so this parameter will affect runtime.
//
// float stb_perlin_ridge_noise3(float x, float y, float z,
// float lacunarity, float gain, float offset, int octaves)
//
// float stb_perlin_fbm_noise3(float x, float y, float z,
// float lacunarity, float gain, int octaves)
//
// float stb_perlin_turbulence_noise3(float x, float y, float z,
// float lacunarity, float gain, int octaves)
//
// Typical values to start playing with:
// octaves = 6 -- number of "octaves" of noise3() to sum
// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output)
// gain = 0.5 -- relative weighting applied to each successive octave
// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure
//
//
// Contributors:
// Jack Mott - additional noise functions
// Jordan Peck - seeded noise
//
#ifdef __cplusplus
extern "C" {
#endif
extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed);
extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves);
extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);
extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);
extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed);
#ifdef __cplusplus
}
#endif
#ifdef STB_PERLIN_IMPLEMENTATION
#include <math.h> // fabs()
// not same permutation table as Perlin's reference to avoid copyright issues;
// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
static unsigned char stb__perlin_randtab[512] =
{
23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
// and a second copy so we don't need an extra mask or static initializer
23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72,
175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240,
8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57,
225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233,
94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172,
165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243,
65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122,
26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76,
250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246,
132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3,
91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231,
38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221,
131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62,
27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135,
61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5,
};
// perlin's gradient has 12 cases so some get used 1/16th of the time
// and some 2/16ths. We reduce bias by changing those fractions
// to 5/64ths and 6/64ths
// this array is designed to match the previous implementation
// of gradient hash: indices[stb__perlin_randtab[i]&63]
static unsigned char stb__perlin_randtab_grad_idx[512] =
{
7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7,
8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8,
7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8,
8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5,
5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1,
2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4,
9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11,
1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6,
10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0,
6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2,
4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3,
11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11,
10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1,
3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10,
11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7,
9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5,
// and a second copy so we don't need an extra mask or static initializer
7, 9, 5, 0, 11, 1, 6, 9, 3, 9, 11, 1, 8, 10, 4, 7,
8, 6, 1, 5, 3, 10, 9, 10, 0, 8, 4, 1, 5, 2, 7, 8,
7, 11, 9, 10, 1, 0, 4, 7, 5, 0, 11, 6, 1, 4, 2, 8,
8, 10, 4, 9, 9, 2, 5, 7, 9, 1, 7, 2, 2, 6, 11, 5,
5, 4, 6, 9, 0, 1, 1, 0, 7, 6, 9, 8, 4, 10, 3, 1,
2, 8, 8, 9, 10, 11, 5, 11, 11, 2, 6, 10, 3, 4, 2, 4,
9, 10, 3, 2, 6, 3, 6, 10, 5, 3, 4, 10, 11, 2, 9, 11,
1, 11, 10, 4, 9, 4, 11, 0, 4, 11, 4, 0, 0, 0, 7, 6,
10, 4, 1, 3, 11, 5, 3, 4, 2, 9, 1, 3, 0, 1, 8, 0,
6, 7, 8, 7, 0, 4, 6, 10, 8, 2, 3, 11, 11, 8, 0, 2,
4, 8, 3, 0, 0, 10, 6, 1, 2, 2, 4, 5, 6, 0, 1, 3,
11, 9, 5, 5, 9, 6, 9, 8, 3, 8, 1, 8, 9, 6, 9, 11,
10, 7, 5, 6, 5, 9, 1, 3, 7, 0, 2, 10, 11, 2, 6, 1,
3, 11, 7, 7, 2, 1, 7, 3, 0, 8, 1, 1, 5, 0, 6, 10,
11, 11, 0, 2, 7, 0, 10, 8, 3, 5, 7, 1, 11, 1, 0, 7,
9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5,
};
static float stb__perlin_lerp(float a, float b, float t)
{
return a + (b-a) * t;
}
static int stb__perlin_fastfloor(float a)
{
int ai = (int) a;
return (a < ai) ? ai-1 : ai;
}
// different grad function from Perlin's, but easy to modify to match reference
static float stb__perlin_grad(int grad_idx, float x, float y, float z)
{
static float basis[12][4] =
{
{ 1, 1, 0 },
{ -1, 1, 0 },
{ 1,-1, 0 },
{ -1,-1, 0 },
{ 1, 0, 1 },
{ -1, 0, 1 },
{ 1, 0,-1 },
{ -1, 0,-1 },
{ 0, 1, 1 },
{ 0,-1, 1 },
{ 0, 1,-1 },
{ 0,-1,-1 },
};
float *grad = basis[grad_idx];
return grad[0]*x + grad[1]*y + grad[2]*z;
}
float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
{
float u,v,w;
float n000,n001,n010,n011,n100,n101,n110,n111;
float n00,n01,n10,n11;
float n0,n1;
unsigned int x_mask = (x_wrap-1) & 255;
unsigned int y_mask = (y_wrap-1) & 255;
unsigned int z_mask = (z_wrap-1) & 255;
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x0 = px & x_mask, x1 = (px+1) & x_mask;
int y0 = py & y_mask, y1 = (py+1) & y_mask;
int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
int r0,r1, r00,r01,r10,r11;
#define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
x -= px; u = stb__perlin_ease(x);
y -= py; v = stb__perlin_ease(y);
z -= pz; w = stb__perlin_ease(z);
r0 = stb__perlin_randtab[x0+seed];
r1 = stb__perlin_randtab[x1+seed];
r00 = stb__perlin_randtab[r0+y0];
r01 = stb__perlin_randtab[r0+y1];
r10 = stb__perlin_randtab[r1+y0];
r11 = stb__perlin_randtab[r1+y1];
n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z );
n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 );
n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z );
n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 );
n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z );
n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 );
n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z );
n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 );
n00 = stb__perlin_lerp(n000,n001,w);
n01 = stb__perlin_lerp(n010,n011,w);
n10 = stb__perlin_lerp(n100,n101,w);
n11 = stb__perlin_lerp(n110,n111,w);
n0 = stb__perlin_lerp(n00,n01,v);
n1 = stb__perlin_lerp(n10,n11,v);
return stb__perlin_lerp(n0,n1,u);
}
float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap)
{
return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap,0);
}
float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed)
{
return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap, (unsigned char) seed);
}
float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves)
{
int i;
float frequency = 1.0f;
float prev = 1.0f;
float amplitude = 0.5f;
float sum = 0.0f;
for (i = 0; i < octaves; i++) {
float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i);
r = offset - (float) fabs(r);
r = r*r;
sum += r*amplitude*prev;
prev = r;
frequency *= lacunarity;
amplitude *= gain;
}
return sum;
}
float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves)
{
int i;
float frequency = 1.0f;
float amplitude = 1.0f;
float sum = 0.0f;
for (i = 0; i < octaves; i++) {
sum += stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return sum;
}
float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves)
{
int i;
float frequency = 1.0f;
float amplitude = 1.0f;
float sum = 0.0f;
for (i = 0; i < octaves; i++) {
float r = stb_perlin_noise3_internal(x*frequency,y*frequency,z*frequency,0,0,0,(unsigned char)i)*amplitude;
sum += (float) fabs(r);
frequency *= lacunarity;
amplitude *= gain;
}
return sum;
}
float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
{
float u,v,w;
float n000,n001,n010,n011,n100,n101,n110,n111;
float n00,n01,n10,n11;
float n0,n1;
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x_wrap2 = (x_wrap ? x_wrap : 256);
int y_wrap2 = (y_wrap ? y_wrap : 256);
int z_wrap2 = (z_wrap ? z_wrap : 256);
int x0 = px % x_wrap2, x1;
int y0 = py % y_wrap2, y1;
int z0 = pz % z_wrap2, z1;
int r0,r1, r00,r01,r10,r11;
if (x0 < 0) x0 += x_wrap2;
if (y0 < 0) y0 += y_wrap2;
if (z0 < 0) z0 += z_wrap2;
x1 = (x0+1) % x_wrap2;
y1 = (y0+1) % y_wrap2;
z1 = (z0+1) % z_wrap2;
#define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
x -= px; u = stb__perlin_ease(x);
y -= py; v = stb__perlin_ease(y);
z -= pz; w = stb__perlin_ease(z);
r0 = stb__perlin_randtab[x0];
r0 = stb__perlin_randtab[r0+seed];
r1 = stb__perlin_randtab[x1];
r1 = stb__perlin_randtab[r1+seed];
r00 = stb__perlin_randtab[r0+y0];
r01 = stb__perlin_randtab[r0+y1];
r10 = stb__perlin_randtab[r1+y0];
r11 = stb__perlin_randtab[r1+y1];
n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z );
n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 );
n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z );
n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 );
n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z );
n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 );
n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z );
n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 );
n00 = stb__perlin_lerp(n000,n001,w);
n01 = stb__perlin_lerp(n010,n011,w);
n10 = stb__perlin_lerp(n100,n101,w);
n11 = stb__perlin_lerp(n110,n111,w);
n0 = stb__perlin_lerp(n00,n01,v);
n1 = stb__perlin_lerp(n10,n11,v);
return stb__perlin_lerp(n0,n1,u);
}
#endif // STB_PERLIN_IMPLEMENTATION
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

View File

@ -1241,6 +1241,7 @@ RLAPI Image GenImageGradientH(int width, int height, Color left, Color right);
RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells
// Image manipulation functions
@ -1286,6 +1287,8 @@ RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX,
RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle within an image
RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw circle within an image (Vector version)
RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image
RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version)
RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
@ -1367,12 +1370,15 @@ RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint);
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
// Text codepoints management functions (unicode characters)
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
RLAPI char *TextCodepointsToUTF8(const int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
// Text strings management functions (no UTF-8 strings, only byte chars)
// NOTE: Some strings allocate memory internally for returned strings, just be careful!

View File

@ -1971,7 +1971,7 @@ void EnableEventWaiting(void)
}
// Disable waiting for events on EndDrawing(), automatic events polling
RLAPI void DisableEventWaiting(void)
void DisableEventWaiting(void)
{
CORE.Window.eventWaiting = false;
}
@ -2472,7 +2472,7 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
}
// Load shader from code strings and bind default locations
RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
{
Shader shader = { 0 };
shader.locs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
@ -3872,22 +3872,7 @@ Vector2 GetTouchPosition(int index)
// https://docs.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages
if (index == 0) position = GetMousePosition();
#endif
#if defined(PLATFORM_ANDROID)
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height))
{
position.x = position.x*((float)CORE.Window.screen.width/(float)(CORE.Window.display.width - CORE.Window.renderOffset.x)) - CORE.Window.renderOffset.x/2;
position.y = position.y*((float)CORE.Window.screen.height/(float)(CORE.Window.display.height - CORE.Window.renderOffset.y)) - CORE.Window.renderOffset.y/2;
}
else
{
position.x = position.x*((float)CORE.Window.render.width/(float)CORE.Window.display.width) - CORE.Window.renderOffset.x/2;
position.y = position.y*((float)CORE.Window.render.height/(float)CORE.Window.display.height) - CORE.Window.renderOffset.y/2;
}
#endif
#if defined(PLATFORM_WEB) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
else TRACELOG(LOG_WARNING, "INPUT: Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
#endif
@ -4038,9 +4023,9 @@ static bool InitGraphicsDevice(int width, int height)
glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0
}
// NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
// with forward compatibility to older OpenGL versions.
// For example, if using OpenGL 1.1, driver can provide a 4.3 context forward compatible.
// NOTE: When asking for an OpenGL context version, most drivers provide the highest supported version
// with backward compatibility to older OpenGL versions.
// For example, if using OpenGL 1.1, driver can provide a 4.3 backwards compatible context.
// Check selection OpenGL version
if (rlGetVersion() == RL_OPENGL_21)
@ -5414,7 +5399,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
// Scan all files and directories recursively from a base path
static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *files, const char *filter)
{
static char path[MAX_FILEPATH_LENGTH] = { 0 };
char path[MAX_FILEPATH_LENGTH] = { 0 };
memset(path, 0, MAX_FILEPATH_LENGTH);
struct dirent *dp = NULL;
@ -5752,7 +5737,14 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Reset screen scaling to full display size
EGLint displayFormat = 0;
eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
ANativeWindow_setBuffersGeometry(app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat);
// Adding renderOffset here feels rather hackish, but the viewport scaling is wrong after the
// context rebinding if the screen is scaled unless offsets are added. There's probably a more
// appropriate way to fix this
ANativeWindow_setBuffersGeometry(app->window,
CORE.Window.render.width + CORE.Window.renderOffset.x,
CORE.Window.render.height + CORE.Window.renderOffset.y,
displayFormat);
// Recreate display surface and re-attach OpenGL context
CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, app->window, NULL);
@ -5841,6 +5833,32 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
}
}
static GamepadButton AndroidTranslateGamepadButton(int button)
{
switch (button)
{
case AKEYCODE_BUTTON_A: return GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
case AKEYCODE_BUTTON_B: return GAMEPAD_BUTTON_RIGHT_FACE_RIGHT;
case AKEYCODE_BUTTON_X: return GAMEPAD_BUTTON_RIGHT_FACE_LEFT;
case AKEYCODE_BUTTON_Y: return GAMEPAD_BUTTON_RIGHT_FACE_UP;
case AKEYCODE_BUTTON_L1: return GAMEPAD_BUTTON_LEFT_TRIGGER_1;
case AKEYCODE_BUTTON_R1: return GAMEPAD_BUTTON_RIGHT_TRIGGER_1;
case AKEYCODE_BUTTON_L2: return GAMEPAD_BUTTON_LEFT_TRIGGER_2;
case AKEYCODE_BUTTON_R2: return GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
case AKEYCODE_BUTTON_THUMBL: return GAMEPAD_BUTTON_LEFT_THUMB;
case AKEYCODE_BUTTON_THUMBR: return GAMEPAD_BUTTON_RIGHT_THUMB;
case AKEYCODE_BUTTON_START: return GAMEPAD_BUTTON_MIDDLE_RIGHT;
case AKEYCODE_BUTTON_SELECT: return GAMEPAD_BUTTON_MIDDLE_LEFT;
case AKEYCODE_BUTTON_MODE: return GAMEPAD_BUTTON_MIDDLE;
// On some (most?) gamepads dpad events are reported as axis motion instead
case AKEYCODE_DPAD_DOWN: return GAMEPAD_BUTTON_LEFT_FACE_DOWN;
case AKEYCODE_DPAD_RIGHT: return GAMEPAD_BUTTON_LEFT_FACE_RIGHT;
case AKEYCODE_DPAD_LEFT: return GAMEPAD_BUTTON_LEFT_FACE_LEFT;
case AKEYCODE_DPAD_UP: return GAMEPAD_BUTTON_LEFT_FACE_UP;
default: return GAMEPAD_BUTTON_UNKNOWN;
}
}
// ANDROID: Get input events
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{
@ -5856,26 +5874,59 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK) ||
((source & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD))
{
// Get first touch position
CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
// For now we'll assume a single gamepad which we "detect" on its input event
CORE.Input.Gamepad.ready[0] = true;
// Get second touch position
CORE.Input.Touch.position[1].x = AMotionEvent_getX(event, 1);
CORE.Input.Touch.position[1].y = AMotionEvent_getY(event, 1);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_X] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_X, 0);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_Y] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_Y, 0);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_X] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_Z, 0);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_Y] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_RZ, 0);
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_LEFT_TRIGGER] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_BRAKE, 0) * 2.0f - 1.0f;
CORE.Input.Gamepad.axisState[0][GAMEPAD_AXIS_RIGHT_TRIGGER] = AMotionEvent_getAxisValue(
event, AMOTION_EVENT_AXIS_GAS, 0) * 2.0f - 1.0f;
int32_t keycode = AKeyEvent_getKeyCode(event);
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
// dpad is reported as an axis on android
float dpadX = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0);
float dpadY = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, 0);
if (dpadX == 1.0f)
{
CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
CORE.Input.Keyboard.keyPressedQueueCount++;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_RIGHT] = 1;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_LEFT] = 0;
}
else if (dpadX == -1.0f)
{
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_RIGHT] = 0;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_LEFT] = 1;
}
else
{
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_RIGHT] = 0;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_LEFT] = 0;
}
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
// Stop processing gamepad buttons
return 1;
if (dpadY == 1.0f)
{
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_DOWN] = 1;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_UP] = 0;
}
else if (dpadY == -1.0f)
{
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_DOWN] = 0;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_UP] = 1;
}
else
{
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_DOWN] = 0;
CORE.Input.Gamepad.currentButtonState[0][GAMEPAD_BUTTON_LEFT_FACE_UP] = 0;
}
return 1; // Handled gamepad axis motion
}
}
else if (type == AINPUT_EVENT_TYPE_KEY)
@ -5883,6 +5934,25 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
int32_t keycode = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
// Handle gamepad button presses and releases
if (((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK) ||
((source & AINPUT_SOURCE_GAMEPAD) == AINPUT_SOURCE_GAMEPAD))
{
// For now we'll assume a single gamepad which we "detect" on its input event
CORE.Input.Gamepad.ready[0] = true;
GamepadButton button = AndroidTranslateGamepadButton(keycode);
if (button == GAMEPAD_BUTTON_UNKNOWN)
return 1;
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
{
CORE.Input.Gamepad.currentButtonState[0][button] = 1;
}
else CORE.Input.Gamepad.currentButtonState[0][button] = 0; // Key up
return 1; // Handled gamepad button
}
// Save current button and its state
// NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
@ -5928,17 +5998,16 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
// Register touch points position
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
// Normalize CORE.Input.Touch.position[x] for screenWidth and screenHeight
CORE.Input.Touch.position[i].x /= (float)GetScreenWidth();
CORE.Input.Touch.position[i].y /= (float)GetScreenHeight();
// 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;
}
int32_t action = AMotionEvent_getAction(event);
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
if (flags == AMOTION_EVENT_ACTION_DOWN || flags == AMOTION_EVENT_ACTION_MOVE) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
else if (flags == AMOTION_EVENT_ACTION_UP) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
#if defined(SUPPORT_GESTURES_SYSTEM) // PLATFORM_ANDROID
GestureEvent gestureEvent = { 0 };
@ -5960,6 +6029,25 @@ 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;
if (CORE.Input.Touch.pointCount > 0) CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 1;
else CORE.Input.Touch.currentTouchState[MOUSE_BUTTON_LEFT] = 0;
return 0;
}
#endif

View File

@ -741,16 +741,11 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif
#if defined(GRAPHICS_API_OPENGL_33)
#if defined(__APPLE__)
#include <OpenGL/gl3.h> // OpenGL 3 library for OSX
#include <OpenGL/gl3ext.h> // OpenGL 3 extensions library for OSX
#else
#define GLAD_MALLOC RL_MALLOC
#define GLAD_FREE RL_FREE
#define GLAD_MALLOC RL_MALLOC
#define GLAD_FREE RL_FREE
#define GLAD_GL_IMPLEMENTATION
#include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers
#endif
#define GLAD_GL_IMPLEMENTATION
#include "external/glad.h" // GLAD extensions loading library, includes OpenGL headers
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
@ -995,14 +990,12 @@ static void rlUnloadShaderDefault(void); // Unload default shader
static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name
#endif // RLGL_SHOW_GL_DETAILS_INFO
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
#if defined(GRAPHICS_API_OPENGL_11)
static int rlGenTextureMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side
static unsigned char *rlGenNextMipmapData(unsigned char *srcData, int srcWidth, int srcHeight); // Generate next mipmap level on CPU side
#endif
static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
// Auxiliar matrix math functions
static Matrix rlMatrixIdentity(void); // Get identity matrix
static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices
static Matrix rlMatrixIdentity(void); // Get identity matrix
static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices
//----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations
@ -2001,10 +1994,8 @@ void rlLoadExtensions(void *loader)
{
#if defined(GRAPHICS_API_OPENGL_33) // Also defined for GRAPHICS_API_OPENGL_21
// NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions)
#if !defined(__APPLE__)
if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
#endif
if (gladLoadGL((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL extensions");
else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL extensions loaded successfully");
// Get number of supported extensions
GLint numExt = 0;
@ -2018,6 +2009,18 @@ void rlLoadExtensions(void *loader)
for (int i = 0; i < numExt; i++) TRACELOG(RL_LOG_INFO, " %s", glGetStringi(GL_EXTENSIONS, i));
#endif
#if defined(GRAPHICS_API_OPENGL_21)
// Register supported extensions flags
// Optional OpenGL 2.1 extensions
RLGL.ExtSupported.vao = GLAD_GL_ARB_vertex_array_object;
RLGL.ExtSupported.instancing = (GLAD_GL_EXT_draw_instanced && GLAD_GL_ARB_instanced_arrays);
RLGL.ExtSupported.texNPOT = GLAD_GL_ARB_texture_non_power_of_two;
RLGL.ExtSupported.texFloat32 = GLAD_GL_ARB_texture_float;
RLGL.ExtSupported.texDepth = GLAD_GL_ARB_depth_texture;
RLGL.ExtSupported.maxDepthBits = 32;
RLGL.ExtSupported.texAnisoFilter = GLAD_GL_EXT_texture_filter_anisotropic;
RLGL.ExtSupported.texMirrorClamp = GLAD_GL_EXT_texture_mirror_clamp;
#else
// Register supported extensions flags
// OpenGL 3.3 extensions supported by default (core)
RLGL.ExtSupported.vao = true;
@ -2028,18 +2031,17 @@ void rlLoadExtensions(void *loader)
RLGL.ExtSupported.maxDepthBits = 32;
RLGL.ExtSupported.texAnisoFilter = true;
RLGL.ExtSupported.texMirrorClamp = true;
#endif
// Optional OpenGL 3.3 extensions
RLGL.ExtSupported.texCompASTC = GLAD_GL_KHR_texture_compression_astc_hdr && GLAD_GL_KHR_texture_compression_astc_ldr;
RLGL.ExtSupported.texCompDXT = GLAD_GL_EXT_texture_compression_s3tc; // Texture compression: DXT
RLGL.ExtSupported.texCompETC2 = GLAD_GL_ARB_ES3_compatibility; // Texture compression: ETC2/EAC
#if defined(GRAPHICS_API_OPENGL_43)
RLGL.ExtSupported.computeShader = GLAD_GL_ARB_compute_shader;
RLGL.ExtSupported.ssbo = GLAD_GL_ARB_shader_storage_buffer_object;
#endif
#if defined(__APPLE__)
// Apple provides its own extension macros
RLGL.ExtSupported.texCompDXT = GL_EXT_texture_compression_s3tc;
#else
// NOTE: With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
RLGL.ExtSupported.texCompDXT = GLAD_GL_EXT_texture_compression_s3tc; // Texture compression: DXT
RLGL.ExtSupported.texCompETC2 = GLAD_GL_ARB_ES3_compatibility; // Texture compression: ETC2/EAC
#endif
#endif // GRAPHICS_API_OPENGL_33
#if defined(GRAPHICS_API_OPENGL_ES2)
@ -2205,12 +2207,10 @@ void rlLoadExtensions(void *loader)
#else // RLGL_SHOW_GL_DETAILS_INFO
// Show some basic info about GL supported features
#if defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.ExtSupported.vao) TRACELOG(RL_LOG_INFO, "GL: VAO extension detected, VAO functions loaded successfully");
else TRACELOG(RL_LOG_WARNING, "GL: VAO extension not found, VAO not supported");
if (RLGL.ExtSupported.texNPOT) TRACELOG(RL_LOG_INFO, "GL: NPOT textures extension detected, full NPOT textures supported");
else TRACELOG(RL_LOG_WARNING, "GL: NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)");
#endif
if (RLGL.ExtSupported.texCompDXT) TRACELOG(RL_LOG_INFO, "GL: DXT compressed textures supported");
if (RLGL.ExtSupported.texCompETC1) TRACELOG(RL_LOG_INFO, "GL: ETC1 compressed textures supported");
if (RLGL.ExtSupported.texCompETC2) TRACELOG(RL_LOG_INFO, "GL: ETC2/EAC compressed textures supported");
@ -2231,11 +2231,7 @@ int rlGetVersion(void)
glVersion = RL_OPENGL_11;
#endif
#if defined(GRAPHICS_API_OPENGL_21)
#if defined(__APPLE__)
glVersion = RL_OPENGL_33; // NOTE: Force OpenGL 3.3 on OSX
#else
glVersion = RL_OPENGL_21;
#endif
glVersion = RL_OPENGL_21;
#elif defined(GRAPHICS_API_OPENGL_33)
glVersion = RL_OPENGL_33;
#endif
@ -3086,6 +3082,7 @@ void rlUnloadTexture(unsigned int id)
}
// Generate mipmap data for selected texture
// NOTE: Only supports GPU mipmap generation
void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int *mipmaps)
{
glBindTexture(GL_TEXTURE_2D, id);
@ -3096,45 +3093,6 @@ void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int
if (((width > 0) && ((width & (width - 1)) == 0)) &&
((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
#if defined(GRAPHICS_API_OPENGL_11)
if (texIsPOT)
{
// WARNING: Manual mipmap generation only works for RGBA 32bit textures!
if (format == RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
{
// Retrieve texture data from VRAM
void *texData = rlReadTexturePixels(id, width, height, format);
// NOTE: Texture data size is reallocated to fit mipmaps data
// NOTE: CPU mipmap generation only supports RGBA 32bit data
int mipmapCount = rlGenTextureMipmapsData(texData, width, height);
int size = width*height*4;
int offset = size;
int mipWidth = width/2;
int mipHeight = height/2;
// Load the mipmaps
for (int level = 1; level < mipmapCount; level++)
{
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, mipWidth, mipHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)texData + offset);
size = mipWidth*mipHeight*4;
offset += size;
mipWidth /= 2;
mipHeight /= 2;
}
*mipmaps = mipmapCount + 1;
RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", id, *mipmaps);
}
else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", id);
}
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
{
@ -4524,132 +4482,6 @@ static char *rlGetCompressedFormatName(int format)
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
#if defined(GRAPHICS_API_OPENGL_11)
// Mipmaps data is generated after image data
// NOTE: Only works with RGBA (4 bytes) data!
static int rlGenTextureMipmapsData(unsigned char *data, int baseWidth, int baseHeight)
{
int mipmapCount = 1; // Required mipmap levels count (including base level)
int width = baseWidth;
int height = baseHeight;
int size = baseWidth*baseHeight*4; // Size in bytes (will include mipmaps...), RGBA only
// Count mipmap levels required
while ((width != 1) && (height != 1))
{
width /= 2;
height /= 2;
TRACELOGD("TEXTURE: Next mipmap size: %i x %i", width, height);
mipmapCount++;
size += (width*height*4); // Add mipmap size (in bytes)
}
TRACELOGD("TEXTURE: Total mipmaps required: %i", mipmapCount);
TRACELOGD("TEXTURE: Total size of data required: %i", size);
unsigned char *temp = RL_REALLOC(data, size);
if (temp != NULL) data = temp;
else TRACELOG(RL_LOG_WARNING, "TEXTURE: Failed to re-allocate required mipmaps memory");
width = baseWidth;
height = baseHeight;
size = (width*height*4); // RGBA: 4 bytes
// Generate mipmaps
// NOTE: Every mipmap data is stored after data (RGBA - 4 bytes)
unsigned char *image = (unsigned char *)RL_MALLOC(width*height*4);
unsigned char *mipmap = NULL;
int offset = 0;
for (int i = 0; i < size; i += 4)
{
image[i] = data[i];
image[i + 1] = data[i + 1];
image[i + 2] = data[i + 2];
image[i + 3] = data[i + 3];
}
TRACELOGD("TEXTURE: Mipmap base size (%ix%i)", width, height);
for (int mip = 1; mip < mipmapCount; mip++)
{
mipmap = rlGenNextMipmapData(image, width, height);
offset += (width*height*4); // Size of last mipmap
width /= 2;
height /= 2;
size = (width*height*4); // Mipmap size to store after offset
// Add mipmap to data
for (int i = 0; i < size; i += 4)
{
data[offset + i] = mipmap[i];
data[offset + i + 1] = mipmap[i + 1];
data[offset + i + 2] = mipmap[i + 2];
data[offset + i + 3] = mipmap[i + 3];
}
RL_FREE(image);
image = mipmap;
mipmap = NULL;
}
RL_FREE(mipmap); // free mipmap data
return mipmapCount;
}
// Manual mipmap generation (basic scaling algorithm)
static unsigned char *rlGenNextMipmapData(unsigned char *srcData, int srcWidth, int srcHeight)
{
int x2 = 0;
int y2 = 0;
unsigned char prow[4] = { 0 };
unsigned char pcol[4] = { 0 };
int width = srcWidth/2;
int height = srcHeight/2;
unsigned char *mipmap = (unsigned char *)RL_MALLOC(width*height*4);
// Scaling algorithm works perfectly (box-filter)
for (int y = 0; y < height; y++)
{
y2 = 2*y;
for (int x = 0; x < width; x++)
{
x2 = 2*x;
prow[0] = (srcData[(y2*srcWidth + x2)*4 + 0] + srcData[(y2*srcWidth + x2 + 1)*4 + 0])/2;
prow[1] = (srcData[(y2*srcWidth + x2)*4 + 1] + srcData[(y2*srcWidth + x2 + 1)*4 + 1])/2;
prow[2] = (srcData[(y2*srcWidth + x2)*4 + 2] + srcData[(y2*srcWidth + x2 + 1)*4 + 2])/2;
prow[3] = (srcData[(y2*srcWidth + x2)*4 + 3] + srcData[(y2*srcWidth + x2 + 1)*4 + 3])/2;
pcol[0] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 0] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 0])/2;
pcol[1] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 1] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 1])/2;
pcol[2] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 2] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 2])/2;
pcol[3] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 3] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 3])/2;
mipmap[(y*width + x)*4 + 0] = (prow[0] + pcol[0])/2;
mipmap[(y*width + x)*4 + 1] = (prow[1] + pcol[1])/2;
mipmap[(y*width + x)*4 + 2] = (prow[2] + pcol[2])/2;
mipmap[(y*width + x)*4 + 3] = (prow[3] + pcol[3])/2;
}
}
TRACELOGD("TEXTURE: Mipmap generated successfully (%ix%i)", width, height);
return mipmap;
}
#endif // GRAPHICS_API_OPENGL_11
// Get pixel data size in bytes (image or texture)
// NOTE: Size depends on pixel format
static int rlGetPixelDataSize(int width, int height, int format)

View File

@ -1043,7 +1043,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -1185,7 +1185,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
byteCounter++;
int next = 0;
letter = GetCodepoint(&text[i], &next);
letter = GetCodepointNext(&text[i], &next);
index = GetGlyphIndex(font, letter);
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -1627,7 +1627,7 @@ const char *TextToPascal(const char *text)
// Encode text codepoint into UTF-8 text
// REQUIRES: memcpy()
// WARNING: Allocated memory must be manually freed
char *TextCodepointsToUTF8(const int *codepoints, int length)
char *LoadUTF8(const int *codepoints, int length)
{
// We allocate enough memory fo fit all possible codepoints
// NOTE: 5 bytes for every codepoint should be enough
@ -1650,9 +1650,68 @@ char *TextCodepointsToUTF8(const int *codepoints, int length)
return text;
}
// Unload UTF-8 text encoded from codepoints array
void UnloadUTF8(char *text)
{
RL_FREE(text);
}
// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
int *LoadCodepoints(const char *text, int *count)
{
int textLength = TextLength(text);
int codepointSize = 0;
int codepointCount = 0;
// Allocate a big enough buffer to store as many codepoints as text bytes
int *codepoints = RL_CALLOC(textLength, sizeof(int));
for (int i = 0; i < textLength; codepointCount++)
{
codepoints[codepointCount] = GetCodepointNext(text + i, &codepointSize);
i += codepointSize;
}
// Re-allocate buffer to the actual number of codepoints loaded
void *temp = RL_REALLOC(codepoints, codepointCount*sizeof(int));
if (temp != NULL) codepoints = temp;
*count = codepointCount;
return codepoints;
}
// Unload codepoints data from memory
void UnloadCodepoints(int *codepoints)
{
RL_FREE(codepoints);
}
// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found
// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead
int GetCodepointCount(const char *text)
{
unsigned int length = 0;
char *ptr = (char *)&text[0];
while (*ptr != '\0')
{
int next = 0;
int letter = GetCodepointNext(ptr, &next);
if (letter == 0x3f) ptr += 1;
else ptr += next;
length++;
}
return length;
}
// Encode codepoint into utf8 text (char array length returned as parameter)
// NOTE: It uses a static array to store UTF-8 bytes
RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize)
const char *CodepointToUTF8(int codepoint, int *utf8Size)
{
static char utf8[6] = { 0 };
int size = 0; // Byte size of codepoint
@ -1684,63 +1743,10 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize)
size = 4;
}
*byteSize = size;
*utf8Size = size;
return utf8;
}
// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
int *LoadCodepoints(const char *text, int *count)
{
int textLength = TextLength(text);
int bytesProcessed = 0;
int codepointCount = 0;
// Allocate a big enough buffer to store as many codepoints as text bytes
int *codepoints = RL_CALLOC(textLength, sizeof(int));
for (int i = 0; i < textLength; codepointCount++)
{
codepoints[codepointCount] = GetCodepoint(text + i, &bytesProcessed);
i += bytesProcessed;
}
// Re-allocate buffer to the actual number of codepoints loaded
void *temp = RL_REALLOC(codepoints, codepointCount*sizeof(int));
if (temp != NULL) codepoints = temp;
*count = codepointCount;
return codepoints;
}
// Unload codepoints data from memory
void UnloadCodepoints(int *codepoints)
{
RL_FREE(codepoints);
}
// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found
// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead
int GetCodepointCount(const char *text)
{
unsigned int length = 0;
char *ptr = (char *)&text[0];
while (*ptr != '\0')
{
int next = 0;
int letter = GetCodepoint(ptr, &next);
if (letter == 0x3f) ptr += 1;
else ptr += next;
length++;
}
return length;
}
#endif // SUPPORT_TEXT_MANIPULATION
// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
@ -1748,7 +1754,7 @@ int GetCodepointCount(const char *text)
// Total number of bytes processed are returned as a parameter
// NOTE: The standard says U+FFFD should be returned in case of errors
// but that character is not supported by the default font in raylib
int GetCodepoint(const char *text, int *bytesProcessed)
int GetCodepoint(const char *text, int *codepointSize)
{
/*
UTF-8 specs from https://www.ietf.org/rfc/rfc3629.txt
@ -1763,14 +1769,14 @@ int GetCodepoint(const char *text, int *bytesProcessed)
*/
// NOTE: on decode errors we return as soon as possible
int code = 0x3f; // Codepoint (defaults to '?')
int codepoint = 0x3f; // Codepoint (defaults to '?')
int octet = (unsigned char)(text[0]); // The first UTF8 octet
*bytesProcessed = 1;
*codepointSize = 1;
if (octet <= 0x7f)
{
// Only one octet (ASCII range x00-7F)
code = text[0];
codepoint = text[0];
}
else if ((octet & 0xe0) == 0xc0)
{
@ -1779,12 +1785,12 @@ int GetCodepoint(const char *text, int *bytesProcessed)
// [0]xC2-DF [1]UTF8-tail(x80-BF)
unsigned char octet1 = text[1];
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *codepointSize = 2; return codepoint; } // Unexpected sequence
if ((octet >= 0xc2) && (octet <= 0xdf))
{
code = ((octet & 0x1f) << 6) | (octet1 & 0x3f);
*bytesProcessed = 2;
codepoint = ((octet & 0x1f) << 6) | (octet1 & 0x3f);
*codepointSize = 2;
}
}
else if ((octet & 0xf0) == 0xe0)
@ -1793,11 +1799,11 @@ int GetCodepoint(const char *text, int *bytesProcessed)
unsigned char octet1 = text[1];
unsigned char octet2 = '\0';
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *codepointSize = 2; return codepoint; } // Unexpected sequence
octet2 = text[2];
if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *bytesProcessed = 3; return code; } // Unexpected sequence
if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *codepointSize = 3; return codepoint; } // Unexpected sequence
// [0]xE0 [1]xA0-BF [2]UTF8-tail(x80-BF)
// [0]xE1-EC [1]UTF8-tail [2]UTF8-tail(x80-BF)
@ -1805,50 +1811,105 @@ int GetCodepoint(const char *text, int *bytesProcessed)
// [0]xEE-EF [1]UTF8-tail [2]UTF8-tail(x80-BF)
if (((octet == 0xe0) && !((octet1 >= 0xa0) && (octet1 <= 0xbf))) ||
((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f)))) { *bytesProcessed = 2; return code; }
((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f)))) { *codepointSize = 2; return codepoint; }
if ((octet >= 0xe0) && (octet <= 0xef))
{
code = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
*bytesProcessed = 3;
codepoint = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
*codepointSize = 3;
}
}
else if ((octet & 0xf8) == 0xf0)
{
// Four octets
if (octet > 0xf4) return code;
if (octet > 0xf4) return codepoint;
unsigned char octet1 = text[1];
unsigned char octet2 = '\0';
unsigned char octet3 = '\0';
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *bytesProcessed = 2; return code; } // Unexpected sequence
if ((octet1 == '\0') || ((octet1 >> 6) != 2)) { *codepointSize = 2; return codepoint; } // Unexpected sequence
octet2 = text[2];
if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *bytesProcessed = 3; return code; } // Unexpected sequence
if ((octet2 == '\0') || ((octet2 >> 6) != 2)) { *codepointSize = 3; return codepoint; } // Unexpected sequence
octet3 = text[3];
if ((octet3 == '\0') || ((octet3 >> 6) != 2)) { *bytesProcessed = 4; return code; } // Unexpected sequence
if ((octet3 == '\0') || ((octet3 >> 6) != 2)) { *codepointSize = 4; return codepoint; } // Unexpected sequence
// [0]xF0 [1]x90-BF [2]UTF8-tail [3]UTF8-tail
// [0]xF1-F3 [1]UTF8-tail [2]UTF8-tail [3]UTF8-tail
// [0]xF4 [1]x80-8F [2]UTF8-tail [3]UTF8-tail
if (((octet == 0xf0) && !((octet1 >= 0x90) && (octet1 <= 0xbf))) ||
((octet == 0xf4) && !((octet1 >= 0x80) && (octet1 <= 0x8f)))) { *bytesProcessed = 2; return code; } // Unexpected sequence
((octet == 0xf4) && !((octet1 >= 0x80) && (octet1 <= 0x8f)))) { *codepointSize = 2; return codepoint; } // Unexpected sequence
if (octet >= 0xf0)
{
code = ((octet & 0x7) << 18) | ((octet1 & 0x3f) << 12) | ((octet2 & 0x3f) << 6) | (octet3 & 0x3f);
*bytesProcessed = 4;
codepoint = ((octet & 0x7) << 18) | ((octet1 & 0x3f) << 12) | ((octet2 & 0x3f) << 6) | (octet3 & 0x3f);
*codepointSize = 4;
}
}
if (code > 0x10ffff) code = 0x3f; // Codepoints after U+10ffff are invalid
if (codepoint > 0x10ffff) codepoint = 0x3f; // Codepoints after U+10ffff are invalid
return code;
return codepoint;
}
// Get next codepoint in a byte sequence and bytes processed
int GetCodepointNext(const char *text, int *codepointSize)
{
const char *ptr = text;
int codepoint = 0x3f; // Codepoint (defaults to '?')
*codepointSize = 0;
// Get current codepoint and bytes processed
if (0xf0 == (0xf8 & ptr[0]))
{
// 4 byte UTF-8 codepoint
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 */
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
codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
*codepointSize = 2;
}
else
{
// 1 byte UTF-8 codepoint
codepoint = ptr[0];
*codepointSize = 1;
}
return codepoint;
}
// Get previous codepoint in a byte sequence and bytes processed
int GetCodepointPrevious(const char *text, int *codepointSize)
{
const char *ptr = text;
int codepoint = 0x3f; // Codepoint (defaults to '?')
int cpSize = 0;
*codepointSize = 0;
// Move to previous codepoint
do ptr--;
while (((0x80 & ptr[0]) != 0) && ((0xc0 & ptr[0]) == 0x80));
codepoint = GetCodepointNext(ptr, &cpSize);
if (codepoint != 0) *codepointSize = cpSize;
return codepoint;
}
//----------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff