2023-05-14 10:21:03 +00:00
// With much thanks to https://benedicthenshaw.com/soft_render_sdl2.html
// --- SETTINGS ---
// BUFFER
// How to buffer pixels.
// 0: Use SDL_Surface (fastest in software)
// 1: Use SDL_Renderer (slow?)
// TODO: Add support for GPU texture
# define ENGINE_SDL_BUFFERTYPE 0
// TRANSPARENCY
// How to draw transparent pixels (SDL_Surface buffer only).
// 0: Do not handle transparency (Fastest but non-square textures will have a halo around them)
// 1: 1-bit transparency (Alpha values under 128 are not drawn)
// 2: 8-bit transparency (Nice but slow)
// TODO: Add support for SDL_Renderer
# define ENGINE_SDL_TRANSPARENCY 1
// --- HACKS ---
// BUFFER
// Use static color conversion. This will speed up rendering, however, the wrong colors may be displayed depending on platform. This only has an effect if ENGINE_SDL_BUFFERTYPE is set to 0.
// 0 = Disable
// 1 = RGBA (raw)
// 2 = BGRA (common)
// TODO: Add custom mode with quicker conversion of known types, and slow conversion for unknown types.
# define ENGINE_SDL_COLOR 2
// INTEGER UPSCALING
// 2 makes the surface scaled 2x, 3 = 3x, etc.
// TODO: Fix ENGINE_SDL_TRANSPARENCY 2
# define ENGINE_SDL_SCALE 5
// SKIP: COLOR
// Skip setting colors every X requests. Set to 2 to skip every second request, 3 for every third, etc.
# define ENGINE_SDL_SKIP_COLOR_INTERVAL 0 // 2
// How many requests to skip, when a skip is encountered.
# define ENGINE_SDL_SKIP_COLOR_AMOUNT 2
// Whether to alternate fields. TODO
# define ENGINE_SDL_SKIP_COLOR_ALTERNATE 0
// SKIP: PIXEL
// Skip setting pixel every X requests.
# define ENGINE_SDL_SKIP_PIXEL_INTERVAL 0 // 2
# define ENGINE_SDL_SKIP_PIXEL_AMOUNT 2
# define ENGINE_SDL_SKIP_PIXEL_ALTERNATE 0
// SKIP: FRAME
# define ENGINE_SDL_SKIP_FRAME_INTERVAL 1
# define ENGINE_SDL_SKIP_FRAME_AMOUNT 1
// Entirely skip changing any colors and pixels on skipped frames, without this, this is pretty useless
# define ENGINE_SDL_SKIP_FRAME_DROP 0
// DO NOT TOUCH THESE
# if (ENGINE_SDL_SKIP_COLOR_INTERVAL > 0 && ENGINE_SDL_SKIP_COLOR_AMOUNT > 0)
# define ENGINE_SDL_SKIP_COLOR 1
# endif
# if (ENGINE_SDL_SKIP_PIXEL_INTERVAL > 0 && ENGINE_SDL_SKIP_PIXEL_AMOUNT > 0)
# define ENGINE_SDL_SKIP_PIXEL 1
# endif
# if (ENGINE_SDL_SKIP_FRAME_INTERVAL > 0 && ENGINE_SDL_SKIP_FRAME_AMOUNT > 0)
# define ENGINE_SDL_SKIP_FRAME 1
# endif
# include <SDL2/SDL.h>
SDL_Window * engine_sdl_window ;
# if (ENGINE_SDL_BUFFERTYPE == 0)
SDL_Surface * engine_sdl_surface ;
Uint32 * engine_sdl_pixels ;
# endif
# if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_Renderer * engine_sdl_renderer ;
# endif
int engine_width = 0 ;
int engine_height = 0 ;
2023-05-14 19:41:46 +00:00
struct ENGINE_EVENT * engine_event_get ( ) {
struct ENGINE_EVENT * event = engine_malloc ( NULL , sizeof ( struct ENGINE_EVENT ) ) ;
2023-05-14 10:21:03 +00:00
SDL_Event sdlevent ;
if ( ! SDL_PollEvent ( & sdlevent ) ) {
struct ENGINE_EVENT_NONE data ;
2023-05-14 19:41:46 +00:00
event - > type = ENGINE_EVENT_TYPE_NONE ;
event - > data = & data ;
2023-05-14 10:21:03 +00:00
return event ;
}
if ( sdlevent . type = = SDL_QUIT ) {
struct ENGINE_EVENT_EXIT data ;
2023-05-14 19:41:46 +00:00
event - > type = ENGINE_EVENT_TYPE_EXIT ;
event - > data = & data ;
2023-05-14 10:21:03 +00:00
return event ;
}
if ( sdlevent . type = = SDL_KEYDOWN | | sdlevent . type = = SDL_KEYUP ) {
if ( sdlevent . key . repeat ! = 0 ) { goto unknown ; }
struct ENGINE_EVENT_INPUTKB data ;
data . pressed = ( sdlevent . type = = SDL_KEYDOWN ) ;
data . key = sdlevent . key . keysym . scancode ;
2023-05-14 19:41:46 +00:00
event - > type = ENGINE_EVENT_TYPE_INPUTKB ;
event - > data = & data ;
2023-05-14 10:21:03 +00:00
return event ;
}
unknown :
struct ENGINE_EVENT_UNKNOWN data ;
2023-05-14 19:41:46 +00:00
event - > type = ENGINE_EVENT_TYPE_UNKNOWN ;
event - > data = & data ;
2023-05-14 10:21:03 +00:00
return event ;
}
2023-05-14 15:48:31 +00:00
void engine_time_sleep ( long long ms ) {
2023-05-14 10:21:03 +00:00
SDL_Delay ( ms ) ;
}
long long engine_time_get ( ) {
return SDL_GetTicks ( ) ;
}
# ifdef ENGINE_SDL_SKIP_FRAME
char engine_sdl_skipf_interval = 0 ;
char engine_sdl_skipf_amount = 0 ;
# endif
# ifdef ENGINE_SDL_SKIP_COLOR
char engine_sdl_skipc_interval = 0 ;
char engine_sdl_skipc_amount = 0 ;
# endif
Uint32 engine_sdl_color ;
2023-05-14 15:48:31 +00:00
void engine_surface_color_set ( char r , char g , char b , char a ) {
2023-05-14 10:21:03 +00:00
# ifdef ENGINE_SDL_SKIP_COLOR
if ( engine_sdl_skipc_interval = = 0 ) {
if ( engine_sdl_skipc_amount = = 0 ) {
engine_sdl_skipc_interval = ENGINE_SDL_SKIP_COLOR_INTERVAL - 1 ;
engine_sdl_skipc_amount = ENGINE_SDL_SKIP_COLOR_AMOUNT ;
} else {
- - engine_sdl_skipc_amount ;
return ;
}
} else {
- - engine_sdl_skipc_interval ;
}
# endif
# if (ENGINE_SDL_SKIP_FRAME == 1 && ENGINE_SDL_SKIP_FRAME_DROP == 1)
if ( engine_sdl_skipf_interval = = 0 & & engine_sdl_skipf_amount > 0 ) {
return ;
}
# endif
# if (ENGINE_SDL_BUFFERTYPE == 0)
# if (ENGINE_SDL_COLOR != 0 || ENGINE_SDL_TRANSPARENCY > 0)
Uint8 * rawcolor = ( Uint8 * ) & engine_sdl_color ; // is doing this ok?
# endif
# if (ENGINE_SDL_COLOR == 1)
rawcolor [ 0 ] = ( Uint8 ) r ;
rawcolor [ 1 ] = ( Uint8 ) g ;
rawcolor [ 2 ] = ( Uint8 ) b ;
rawcolor [ 3 ] = ( Uint8 ) a ;
# elif (ENGINE_SDL_COLOR == 2)
rawcolor [ 0 ] = ( Uint8 ) b ;
rawcolor [ 1 ] = ( Uint8 ) g ;
rawcolor [ 2 ] = ( Uint8 ) r ;
rawcolor [ 3 ] = ( Uint8 ) a ;
# else
engine_sdl_color = SDL_MapRGBA ( engine_sdl_surface - > format , ( Uint8 ) r , ( Uint8 ) g , ( Uint8 ) b , ( Uint8 ) a ) ;
# if (ENGINE_SDL_TRANSPARENCY > 0)
rawcolor [ 3 ] = ( Uint8 ) a ;
# endif
# endif
# endif
# if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_SetRenderDrawColor ( engine_sdl_renderer , r , g , b , a ) ;
# endif
}
# ifdef ENGINE_SDL_SKIP_PIXEL
char engine_sdl_skipp_interval = 0 ;
char engine_sdl_skipp_amount = 0 ;
# endif
2023-05-14 15:48:31 +00:00
void engine_surface_draw_pixel ( int x , int y ) {
2023-05-14 10:21:03 +00:00
# ifdef ENGINE_SDL_SKIP_PIXEL
if ( engine_sdl_skipp_interval = = 0 ) {
if ( engine_sdl_skipp_amount = = 0 ) {
engine_sdl_skipp_interval = ENGINE_SDL_SKIP_PIXEL_INTERVAL - 1 ;
engine_sdl_skipp_amount = ENGINE_SDL_SKIP_PIXEL_AMOUNT ;
} else {
- - engine_sdl_skipp_amount ;
return ;
}
} else {
- - engine_sdl_skipp_interval ;
}
# endif
# if (ENGINE_SDL_SKIP_FRAME == 1 && ENGINE_SDL_SKIP_FRAME_DROP == 1)
if ( engine_sdl_skipf_interval = = 0 & & engine_sdl_skipf_amount > 0 ) {
return ;
}
# endif
# if (ENGINE_SDL_BUFFERTYPE == 0)
# if (ENGINE_SDL_TRANSPARENCY == 1)
if ( ( ( Uint8 * ) & engine_sdl_color ) [ 3 ] < 128 ) { // is doing this ok?
return ;
}
# endif
# if (ENGINE_SDL_TRANSPARENCY == 2)
Uint8 * rawcolor = ( Uint8 * ) & engine_sdl_color ;
if ( rawcolor [ 3 ] < 255 ) {
Uint8 * sourcecolor = ( Uint8 * ) & engine_sdl_pixels [ x + y * engine_width ] ;
float alpha = ( float ) rawcolor [ 3 ] / 255 ;
sourcecolor [ 0 ] = sourcecolor [ 0 ] + ( ( rawcolor [ 0 ] - sourcecolor [ 0 ] ) * alpha ) ;
sourcecolor [ 1 ] = sourcecolor [ 1 ] + ( ( rawcolor [ 1 ] - sourcecolor [ 1 ] ) * alpha ) ;
sourcecolor [ 2 ] = sourcecolor [ 2 ] + ( ( rawcolor [ 2 ] - sourcecolor [ 2 ] ) * alpha ) ;
return ;
}
# endif
# if (ENGINE_SDL_SCALE == 1)
engine_sdl_pixels [ x + y * engine_width ] = engine_sdl_color ;
# else
char xi = 0 ;
while ( xi < ENGINE_SDL_SCALE ) {
char yi = 0 ;
while ( yi < ENGINE_SDL_SCALE ) {
engine_sdl_pixels [ ( ( x * ENGINE_SDL_SCALE ) + xi ) + ( ( y * ENGINE_SDL_SCALE ) + yi ) * ( engine_width * ENGINE_SDL_SCALE ) ] = engine_sdl_color ;
+ + yi ;
}
+ + xi ;
}
# endif
# endif
# if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_RenderDrawPoint ( engine_sdl_renderer , x , y ) ;
# endif
}
2023-05-14 15:48:31 +00:00
void engine_window_present ( ) {
2023-05-14 10:21:03 +00:00
# ifdef ENGINE_SDL_SKIP_FRAME
if ( engine_sdl_skipf_interval = = 0 ) {
if ( engine_sdl_skipf_amount = = 0 ) {
engine_sdl_skipf_interval = ENGINE_SDL_SKIP_FRAME_INTERVAL - 1 ;
engine_sdl_skipf_amount = ENGINE_SDL_SKIP_FRAME_AMOUNT ;
} else {
- - engine_sdl_skipf_amount ;
return ;
}
} else {
- - engine_sdl_skipf_interval ;
}
# endif
# if (ENGINE_SDL_BUFFERTYPE == 0)
SDL_UpdateWindowSurface ( engine_sdl_window ) ;
# endif
# if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_RenderPresent ( engine_sdl_renderer ) ;
# endif
}
2023-05-14 15:48:31 +00:00
void engine_window_init ( int width , int height , char * title ) {
2023-05-14 10:21:03 +00:00
SDL_Init ( SDL_INIT_VIDEO ) ;
engine_sdl_window = SDL_CreateWindow ( title , SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , width * ENGINE_SDL_SCALE , height * ENGINE_SDL_SCALE , 0 ) ;
# if (ENGINE_SDL_BUFFERTYPE == 0)
engine_sdl_surface = SDL_GetWindowSurface ( engine_sdl_window ) ;
engine_sdl_pixels = engine_sdl_surface - > pixels ;
# endif
# if (ENGINE_SDL_BUFFERTYPE == 1)
engine_sdl_renderer = SDL_CreateRenderer ( engine_sdl_window , - 1 , 0 ) ;
# endif
engine_width = width ;
engine_height = height ;
# if (ENGINE_SDL_BUFFERTYPE == 1)
2023-05-14 15:48:31 +00:00
engine_surface_color_set ( 0 , 0 , 0 , 255 ) ;
2023-05-14 10:21:03 +00:00
# ifdef ENGINE_SDL_SKIP_COLOR
engine_sdl_skipc_interval = 0 ;
engine_sdl_skipc_amount = 0 ;
# endif
SDL_RenderClear ( engine_sdl_renderer ) ;
# endif
}