@ -1,6 +1,6 @@
/**********************************************************************************************
/**********************************************************************************************
*
*
* rl_gputex v1 .0 - GPU compressed textures loading and saving
* rl_gputex v1 .1 - GPU compressed textures loading and saving
*
*
* DESCRIPTION :
* DESCRIPTION :
*
*
@ -10,8 +10,15 @@
* Note that some file formats ( DDS , PVR , KTX ) also support uncompressed data storage .
* Note that some file formats ( DDS , PVR , KTX ) also support uncompressed data storage .
* In those cases data is loaded uncompressed and format is returned .
* In those cases data is loaded uncompressed and format is returned .
*
*
* FIXME : This library still depends on Raylib due to the following reasons :
* - rl_save_ktx_to_memory ( ) requires rlGetGlTextureFormats ( ) from rlgl . h
* though this is not a problem , if you don ' t need KTX support
* - all constants starting with PIXELFORMAT_ * come from raylib . h
* this one is pretty hard to change , because it depends on exact ABI of ' enum PixelFormat '
* however , you can copy - paste said enum or include the header without Raylib sources
* - ( probably ) few minor issues that are hidden by Raylib inclusion and haven ' t been spotted yet
*
* TODO :
* TODO :
* - Implement raylib function : rlGetGlTextureFormats ( ) , required by rl_save_ktx_to_memory ( )
* - Review rl_load_ktx_from_memory ( ) to support KTX v2 .2 specs
* - Review rl_load_ktx_from_memory ( ) to support KTX v2 .2 specs
*
*
* CONFIGURATION :
* CONFIGURATION :
@ -23,6 +30,40 @@
* # define RL_GPUTEX_SUPPORT_ASTC
* # define RL_GPUTEX_SUPPORT_ASTC
* Define desired file formats to be supported
* Define desired file formats to be supported
*
*
* # define RL_GPUTEX_SHOW_WARN_INFO
* Define , if you wish to see warnings generated by the library
* This will include < stdio . h > unless you provide your own RL_GPUTEX_WARN
* # define RL_GPUTEX_WARN
* Define , if you wish to provide your own warning function
* Make sure that this macro puts newline character ' \n ' at the end
*
* # define RL_GPUTEX_MALLOC
* # define RL_GPUTEX_CALLOC
* # define RL_GPUTEX_REALLOC
* # define RL_GPUTEX_FREE
* Define those macros in order to provide your own libc - compliant allocator ;
* not doing so will include < stdlib . h >
* If you ' re providing any of those , you must provide ALL of them ,
* otherwise the code will ( most likely ) crash . . .
*
* # define RL_GPUTEX_NULL
* Define in order to provide your own libc - compliant NULL pointer ;
* not doing so will include < stdlib . h >
*
* # define RL_GPUTEX_MEMCPY
* Define in order to provide your own libc - compliant ' memcpy ' function ;
* not doing so will include < string . h >
*
* # define RLGPUTEXAPI
* Define to compiler - specific intrinsic , if you wish to export public functions
* There is no need to do so when statically linking
*
* VERSIONS HISTORY :
* 1.0 ( 17 - Sep - 2022 ) First version has been created by migrating part of compressed - texture - loading
* functionality from Raylib src / rtextures . c into self - contained library
* 1.1 ( 15 - Jul - 2025 ) Several minor fixes related to specific image formats ; some work has been done
* in order to decouple the library from Raylib by introducing few new macros ; library still
* requires Raylib in order to function properly
*
*
* LICENSE : zlib / libpng
* LICENSE : zlib / libpng
*
*
@ -48,8 +89,8 @@
# ifndef RL_GPUTEX_H
# ifndef RL_GPUTEX_H
# define RL_GPUTEX_H
# define RL_GPUTEX_H
# ifndef RLAPI
# define RLAPI / / Functions defined as 'extern' by default (implicit specifiers)
# ifndef RLGPUTEX API
# define RLGPUTEX API / / Functions defined as 'extern' by default (implicit specifiers)
# endif
# endif
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -60,13 +101,13 @@ extern "C" { // Prevents name mangling of functions
# endif
# endif
/ / Load image data from memory data files
/ / 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 ) ;
RLGPUTEX API void * rl_load_dds_from_memory ( const unsigned char * file_data , unsigned int file_size , int * width , int * height , int * format , int * mips ) ;
RLGPUTEX API void * rl_load_pkm_from_memory ( const unsigned char * file_data , unsigned int file_size , int * width , int * height , int * format , int * mips ) ;
RLGPUTEX API void * rl_load_ktx_from_memory ( const unsigned char * file_data , unsigned int file_size , int * width , int * height , int * format , int * mips ) ;
RLGPUTEX API void * rl_load_pvr_from_memory ( const unsigned char * file_data , unsigned int file_size , int * width , int * height , int * format , int * mips ) ;
RLGPUTEX API 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
RLGPUTEX API 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)
# if defined(__cplusplus)
}
}
@ -83,13 +124,57 @@ RLAPI int rl_save_ktx_to_memory(const char *fileName, void *data, int width, int
# if defined(RL_GPUTEX_IMPLEMENTATION)
# if defined(RL_GPUTEX_IMPLEMENTATION)
/ / Simple log system to avoid RPNG_LOG ( ) calls if required
# if defined(RL_GPUTEX_SHOW_WARN_INFO) && !defined(RL_GPUTEX_WARN)
# include <stdio.h> // Required for: printf()
# endif
# if !defined(RL_GPUTEX_MALLOC) || !defined(RL_GPUTEX_NULL)
# include <stdlib.h> // Required for: NULL, malloc(), calloc(), free(), realloc()
# endif
# if !defined(RL_GPUTEX_MEMCPY)
# include <string.h> // Required for: memcpy()
# endif
# if defined(RL_GPUTEX_SUPPORT_KTX) && !defined(RAYLIB_H)
# error "FIXME: RL_GPUTEX_SUPPORT_KTX require Raylib function: rlGetGlTextureFormats()"
# endif
# if defined(RL_GPUTEX_MALLOC) || defined(RL_GPUTEX_CALLOC) || defined(RL_GPUTEX_REALLOC) || defined(RL_GPUTEX_FREE)
# if !defined(RL_GPUTEX_MALLOC) || !defined(RL_GPUTEX_CALLOC) || !defined(RL_GPUTEX_REALLOC) || !defined(RL_GPUTEX_FREE)
# error "You must provide all RL_GPUTEX_* allocating functions - not just few!"
# endif
# endif
# if !defined(RL_GPUTEX_MALLOC)
# define RL_GPUTEX_MALLOC(sz) malloc(sz)
# define RL_GPUTEX_CALLOC(num, sz) calloc(num, sz)
# define RL_GPUTEX_REALLOC(ptr, sz) realloc(ptr, sz)
# define RL_GPUTEX_FREE(ptr) free(ptr)
# endif
# if !defined(RL_GPUTEX_NULL)
# define RL_GPUTEX_NULL NULL
# endif
# if !defined(RL_GPUTEX_MEMCPY)
# define RL_GPUTEX_MEMCPY(dest, src, num) memcpy(dest, src, num)
# endif
/ / Simple warning system to avoid RPNG_LOG ( ) calls if required
/ / NOTE : Avoiding those calls , also avoids const strings memory usage
/ / 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__)
/ / WARN : This macro expects that newline character is added automatically
/ / in order to match the functionality of Raylib ' s TRACELOG ( )
# if defined(RL_GPUTEX_SHOW_WARN_INFO)
# if !defined(RL_GPUTEX_WARN)
# define RL_GPUTEX_WARN(...) (void)(printf("RL_GPUTEX: WARNING: " __VA_ARGS__), printf("\n"))
# endif
# else
# else
# define LOG(...)
# if defined(RL_GPUTEX_WARN)
/ / undefine it first in order to supress warnings about macro redefinition
# undef RL_GPUTEX_WARN
# endif
# define RL_GPUTEX_WARN(...)
# endif
# endif
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -105,8 +190,8 @@ static int get_pixel_data_size(int width, int height, int format);
/ / Loading DDS from memory image data ( compressed or uncompressed )
/ / 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 * 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 = b ">NULL ; / / Image data pointer
int image_pixel_size = 0 ; / / Image pixel size
void * image_data = RL_GPUTEX_ NULL; / / Image data pointer
int image_pixel_size = 0 ; / / Image pixel size
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
@ -153,7 +238,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
unsigned int reserved2 ;
unsigned int reserved2 ;
} dds_header ;
} dds_header ;
if ( file_data_ptr ! = b ">NULL )
if ( file_data_ptr ! = RL_GPUTEX_ NULL)
{
{
/ / Verify the type of file
/ / Verify the type of file
unsigned char * dds_header_id = file_data_ptr ;
unsigned char * dds_header_id = file_data_ptr ;
@ -161,7 +246,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if ( ( dds_header_id [ 0 ] ! = ' D ' ) | | ( dds_header_id [ 1 ] ! = ' D ' ) | | ( dds_header_id [ 2 ] ! = ' S ' ) | | ( dds_header_id [ 3 ] ! = ' ' ) )
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" ) ;
RL_GPUTEX_WARN ( " DDS file data not valid " ) ;
}
}
else
else
{
{
@ -172,8 +257,8 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
* width = header - > width ;
* width = header - > width ;
* height = header - > height ;
* height = header - > height ;
if ( * width % 4 ! = 0 ) LOG ( " WARNING: IMAGE: DDS file width must be multiple of 4. Image will not display correctly" ) ;
if ( * height % 4 ! = 0 ) LOG ( " WARNING: IMAGE: DDS file height must be multiple of 4. Image will not display correctly" ) ;
if ( * width % 4 ! = 0 ) RL_GPUTEX_WARN ( " DDS file width must be multiple of 4. Image will not display correctly " ) ;
if ( * height % 4 ! = 0 ) RL_GPUTEX_WARN ( " DDS file height must be multiple of 4. Image will not display correctly " ) ;
image_pixel_size = header - > width * header - > height ;
image_pixel_size = header - > width * header - > height ;
@ -186,9 +271,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
{
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
image_data = RL_MALLOC ( data_size ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
* format = PIXELFORMAT_UNCOMPRESSED_R5G6B5 ;
* format = PIXELFORMAT_UNCOMPRESSED_R5G6B5 ;
}
}
@ -198,9 +283,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
{
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
image_data = RL_MALLOC ( data_size ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
unsigned char alpha = 0 ;
unsigned char alpha = 0 ;
@ -218,9 +303,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
{
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
int data_size = image_pixel_size * sizeof ( unsigned short ) ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
image_data = RL_MALLOC ( data_size ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
unsigned char alpha = 0 ;
unsigned char alpha = 0 ;
@ -240,9 +325,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
{
int data_size = image_pixel_size * 3 * sizeof ( unsigned char ) ;
int data_size = image_pixel_size * 3 * sizeof ( unsigned char ) ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
image_data = RL_MALLOC ( data_size ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
* format = PIXELFORMAT_UNCOMPRESSED_R8G8B8 ;
* format = PIXELFORMAT_UNCOMPRESSED_R8G8B8 ;
}
}
@ -250,9 +335,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
{
{
int data_size = image_pixel_size * 4 * sizeof ( unsigned char ) ;
int data_size = image_pixel_size * 4 * sizeof ( unsigned char ) ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = data_size + data_size / 3 ;
image_data = RL_MALLOC ( data_size ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
unsigned char blue = 0 ;
unsigned char blue = 0 ;
@ -276,9 +361,9 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
if ( header - > mipmap_count > 1 ) data_size = header - > pitch_or_linear_size + header - > pitch_or_linear_size / 3 ;
if ( header - > mipmap_count > 1 ) data_size = header - > pitch_or_linear_size + header - > pitch_or_linear_size / 3 ;
else data_size = header - > pitch_or_linear_size ;
else data_size = header - > pitch_or_linear_size ;
image_data = RL_MALLOC ( data_size * sizeof ( unsigned char ) ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size * sizeof ( unsigned char ) ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
switch ( header - > ddspf . fourcc )
switch ( header - > ddspf . fourcc )
{
{
@ -305,7 +390,7 @@ void *rl_load_dds_from_memory(const unsigned char *file_data, unsigned int file_
/ / PKM is a much simpler file format used mainly to contain a single ETC1 / ETC2 compressed image ( no 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 * 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 = b ">NULL ; / / Image data pointer
void * image_data = RL_GPUTEX_ NULL; / / Image data pointer
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
@ -336,13 +421,13 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
/ / NOTE : The extended width and height are the widths rounded up to a multiple of 4.
/ / NOTE : The extended width and height are the widths rounded up to a multiple of 4.
/ / NOTE : ETC is always 4 bit per pixel ( 64 bit for each 4 x4 block of pixels )
/ / NOTE : ETC is always 4 bit per pixel ( 64 bit for each 4 x4 block of pixels )
if ( file_data_ptr ! = b ">NULL )
if ( file_data_ptr ! = RL_GPUTEX_ NULL)
{
{
pkm_header * header = ( pkm_header * ) file_data_ptr ;
pkm_header * header = ( pkm_header * ) file_data_ptr ;
if ( ( header - > id [ 0 ] ! = ' P ' ) | | ( header - > id [ 1 ] ! = ' K ' ) | | ( header - > id [ 2 ] ! = ' M ' ) | | ( header - > id [ 3 ] ! = ' ' ) )
if ( ( header - > id [ 0 ] ! = ' P ' ) | | ( header - > id [ 1 ] ! = ' K ' ) | | ( header - > id [ 2 ] ! = ' M ' ) | | ( header - > id [ 3 ] ! = ' ' ) )
{
{
LOG ( " WARNING: IMAGE: PKM file data not valid" ) ;
RL_GPUTEX_WARN ( " PKM file data not valid " ) ;
}
}
else
else
{
{
@ -362,9 +447,9 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Total data size in bytes
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Total data size in bytes
image_data = RL_MALLOC ( data_size * sizeof ( unsigned char ) ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size * sizeof ( unsigned char ) ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
if ( header - > format = = 0 ) * format = PIXELFORMAT_COMPRESSED_ETC1_RGB ;
if ( header - > format = = 0 ) * format = PIXELFORMAT_COMPRESSED_ETC1_RGB ;
else if ( header - > format = = 1 ) * format = PIXELFORMAT_COMPRESSED_ETC2_RGB ;
else if ( header - > format = = 1 ) * format = PIXELFORMAT_COMPRESSED_ETC2_RGB ;
@ -381,7 +466,7 @@ void *rl_load_pkm_from_memory(const unsigned char *file_data, unsigned int file_
/ / TODO : Review KTX loading , many things changed !
/ / 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 * 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 = b ">NULL ; / / Image data pointer
void * image_data = RL_GPUTEX_ NULL; / / Image data pointer
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
@ -419,14 +504,14 @@ void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_
/ / NOTE : Before start of every mipmap data block , we have : unsigned int data_size
/ / NOTE : Before start of every mipmap data block , we have : unsigned int data_size
if ( file_data_ptr ! = b ">NULL )
if ( file_data_ptr ! = RL_GPUTEX_ NULL)
{
{
ktx_header * header = ( ktx_header * ) file_data_ptr ;
ktx_header * header = ( ktx_header * ) file_data_ptr ;
if ( ( header - > id [ 1 ] ! = ' K ' ) | | ( header - > id [ 2 ] ! = ' T ' ) | | ( header - > id [ 3 ] ! = ' X ' ) | |
if ( ( header - > id [ 1 ] ! = ' K ' ) | | ( header - > id [ 2 ] ! = ' T ' ) | | ( header - > id [ 3 ] ! = ' X ' ) | |
( header - > id [ 4 ] ! = ' ' ) | | ( header - > id [ 5 ] ! = ' 1 ' ) | | ( header - > id [ 6 ] ! = ' 1 ' ) )
( header - > id [ 4 ] ! = ' ' ) | | ( header - > id [ 5 ] ! = ' 1 ' ) | | ( header - > id [ 6 ] ! = ' 1 ' ) )
{
{
LOG ( " WARNING: IMAGE: KTX file data not valid" ) ;
RL_GPUTEX_WARN ( " KTX file data not valid " ) ;
}
}
else
else
{
{
@ -441,9 +526,9 @@ void *rl_load_ktx_from_memory(const unsigned char *file_data, unsigned int file_
int data_size = ( ( int * ) file_data_ptr ) [ 0 ] ;
int data_size = ( ( int * ) file_data_ptr ) [ 0 ] ;
file_data_ptr + = sizeof ( int ) ;
file_data_ptr + = sizeof ( int ) ;
image_data = RL_MALLOC ( data_size * sizeof ( unsigned char ) ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size * sizeof ( unsigned char ) ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
if ( header - > gl_internal_format = = 0x8D64 ) * format = PIXELFORMAT_COMPRESSED_ETC1_RGB ;
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 = = 0x9274 ) * format = PIXELFORMAT_COMPRESSED_ETC2_RGB ;
@ -492,7 +577,7 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
w / = 2 ; h / = 2 ;
w / = 2 ; h / = 2 ;
}
}
unsigned char * file_data = RL_CALLOC ( data_size , 1 ) ;
unsigned char * file_data = RL_GPUTEX_ CALLOC ( data_size , 1 ) ;
unsigned char * file_data_ptr = file_data ;
unsigned char * file_data_ptr = file_data ;
ktx_header header = { 0 } ;
ktx_header header = { 0 } ;
@ -504,7 +589,7 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
const char ktx_identifier [ 12 ] = { 0xAB , ' K ' , ' T ' , ' X ' , ' ' , ' 1 ' , ' 1 ' , 0xBB , ' \r ' , ' \n ' , 0x1A , ' \n ' } ;
const char ktx_identifier [ 12 ] = { 0xAB , ' K ' , ' T ' , ' X ' , ' ' , ' 1 ' , ' 1 ' , 0xBB , ' \r ' , ' \n ' , 0x1A , ' \n ' } ;
/ / Get the image header
/ / Get the image header
memcpy ( header . id , ktx_identifier , 12 ) ; / / KTX 1.1 signature
RL_GPUTEX_MEMCPY ( header . id , ktx_identifier , 12 ) ; / / KTX 1.1 signature
header . endianness = 0 ;
header . endianness = 0 ;
header . gl_type = 0 ; / / Obtained from format
header . gl_type = 0 ; / / Obtained from format
header . gl_type_size = 1 ;
header . gl_type_size = 1 ;
@ -524,10 +609,10 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
/ / NOTE : We can save into a . ktx all PixelFormats supported by raylib , including compressed formats like DXT , ETC or ASTC
/ / 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 ) ;
if ( header . gl_format = = - 1 ) RL_GPUTEX_WARN ( " GL format not supported for KTX export (%i) " , header . gl_format ) ;
else
else
{
{
memcpy ( file_data_ptr , & header , sizeof ( ktx_header ) ) ;
RL_GPUTEX_MEMCPY ( file_data_ptr , & header , sizeof ( ktx_header ) ) ;
file_data_ptr + = sizeof ( ktx_header ) ;
file_data_ptr + = sizeof ( ktx_header ) ;
int temp_width = width ;
int temp_width = width ;
@ -539,8 +624,8 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
{
{
unsigned int data_size = get_pixel_data_size ( temp_width , temp_height , format ) ;
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 ) ;
RL_GPUTEX_MEMCPY ( file_data_ptr , & data_size , sizeof ( unsigned int ) ) ;
RL_GPUTEX_MEMCPY ( file_data_ptr + 4 , ( unsigned char * ) data + data_offset , data_size ) ;
temp_width / = 2 ;
temp_width / = 2 ;
temp_height / = 2 ;
temp_height / = 2 ;
@ -553,20 +638,22 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
int success = false ;
int success = false ;
FILE * file = fopen ( file_name , " wb " ) ;
FILE * file = fopen ( file_name , " wb " ) ;
if ( file ! = b ">NULL )
if ( file ! = RL_GPUTEX_ NULL)
{
{
unsigned int count = ( unsigned int ) fwrite ( file_data , sizeof ( unsigned char ) , data_size , file ) ;
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 nf">LOG ( " INFO: FILEIO: [%s] File saved successfully " , file_name ) ;
if ( count = = 0 ) RL_GPUTEX_WARN ( " FILEIO: [%s] Failed to write file " , file_name ) ;
else if ( count ! = data_size ) RL_GPUTEX_WARN ( " FILEIO: [%s] File partially written " , file_name ) ;
else p">( void ) 0 ; / / WARN : this branch is handled by Raylib , since rl_gputex only prints warnings
int result = fclose ( file ) ;
int result = fclose ( file ) ;
if ( result = = 0 ) success = true ;
if ( result ! = 0 ) RL_GPUTEX_WARN ( " FILEIO: [%s] Failed to close file " , file_name ) ;
if ( result = = 0 & & count = = data_size ) success = true ;
}
}
else LOG ( " WARNING: FILEIO: [%s] Failed to open file " , file_name ) ;
else RL_GPUTEX_WARN ( " FILEIO: [%s] Failed to open file " , file_name ) ;
RL_FREE ( file_data ) ; / / Free file data buffer
RL_GPUTEX_ FREE ( file_data ) ; / / Free file data buffer
/ / If all data has been written correctly to file , success = 1
/ / If all data has been written correctly to file , success = 1
return success ;
return success ;
@ -578,7 +665,7 @@ int rl_save_ktx(const char *file_name, void *data, int width, int height, int fo
/ / NOTE : PVR v2 not supported , use PVR v3 instead
/ / 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 * 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 = b ">NULL ; / / Image data pointer
void * image_data = RL_GPUTEX_ NULL; / / Image data pointer
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
@ -636,7 +723,7 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
} PVRMetadata ;
} PVRMetadata ;
# endif
# endif
if ( file_data_ptr ! = b ">NULL )
if ( file_data_ptr ! = RL_GPUTEX_ NULL)
{
{
/ / Check PVR image version
/ / Check PVR image version
unsigned char pvr_version = file_data_ptr [ 0 ] ;
unsigned char pvr_version = file_data_ptr [ 0 ] ;
@ -648,7 +735,7 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
if ( ( header - > id [ 0 ] ! = ' P ' ) | | ( header - > id [ 1 ] ! = ' V ' ) | | ( header - > id [ 2 ] ! = ' R ' ) | | ( header - > id [ 3 ] ! = 3 ) )
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" ) ;
RL_GPUTEX_WARN ( " PVR file data not valid " ) ;
}
}
else
else
{
{
@ -697,12 +784,12 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
}
}
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Total data size in bytes
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Total data size in bytes
image_data = RL_MALLOC ( data_size * sizeof ( unsigned char ) ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size * sizeof ( unsigned char ) ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_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" ) ;
else if ( pvr_version = = 52 ) RL_GPUTEX_WARN ( " PVRv2 format not supported, update your files to PVRv3 " ) ;
}
}
return image_data ;
return image_data ;
@ -713,7 +800,7 @@ void *rl_load_pvr_from_memory(const unsigned char *file_data, unsigned int file_
/ / Load ASTC compressed image data ( ASTC compression )
/ / 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 * 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 = b ">NULL ; / / Image data pointer
void * image_data = RL_GPUTEX_ NULL; / / Image data pointer
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
unsigned char * file_data_ptr = ( unsigned char * ) file_data ;
@ -736,13 +823,13 @@ void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file
unsigned char length [ 3 ] ; / / void * Z - size ( 1 for 2 D images )
unsigned char length [ 3 ] ; / / void * Z - size ( 1 for 2 D images )
} astc_header ;
} astc_header ;
if ( file_data_ptr ! = b ">NULL )
if ( file_data_ptr ! = RL_GPUTEX_ NULL)
{
{
astc_header * header = ( astc_header * ) file_data_ptr ;
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 ) )
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" ) ;
RL_GPUTEX_WARN ( " ASTC file data not valid " ) ;
}
}
else
else
{
{
@ -761,14 +848,14 @@ void *rl_load_astc_from_memory(const unsigned char *file_data, unsigned int file
{
{
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Data size in bytes
int data_size = ( * width ) * ( * height ) * bpp / 8 ; / / Data size in bytes
image_data = RL_MALLOC ( data_size * sizeof ( unsigned char ) ) ;
image_data = RL_GPUTEX_ MALLOC ( data_size * sizeof ( unsigned char ) ) ;
memcpy ( image_data , file_data_ptr , data_size ) ;
RL_GPUTEX_MEMCPY ( image_data , file_data_ptr , data_size ) ;
if ( bpp = = 8 ) * format = PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA ;
if ( bpp = = 8 ) * format = PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA ;
else if ( bpp = = 2 ) * format = PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA ;
else if ( bpp = = 2 ) * format = PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA ;
}
}
else LOG ( " WARNING: IMAGE: ASTC block size configuration not supported" ) ;
else RL_GPUTEX_WARN ( " ASTC block size configuration not supported " ) ;
}
}
}
}