forked from Fierelier/me.fier.engine
297 lines
8.4 KiB
C
297 lines
8.4 KiB
C
// 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;
|
|
|
|
struct ENGINE_EVENT * engine_event_get() {
|
|
struct ENGINE_EVENT * event = engine_malloc(NULL,sizeof(struct ENGINE_EVENT));
|
|
SDL_Event sdlevent;
|
|
|
|
if (!SDL_PollEvent(&sdlevent)) {
|
|
struct ENGINE_EVENT_NONE * data = engine_malloc(NULL,sizeof(struct ENGINE_EVENT_NONE));
|
|
event->type = ENGINE_EVENT_TYPE_NONE;
|
|
event->data = data;
|
|
return event;
|
|
}
|
|
|
|
if (sdlevent.type == SDL_QUIT) {
|
|
struct ENGINE_EVENT_EXIT * data = engine_malloc(NULL,sizeof(struct ENGINE_EVENT_EXIT));;
|
|
event->type = ENGINE_EVENT_TYPE_EXIT;
|
|
event->data = data;
|
|
return event;
|
|
}
|
|
|
|
if (sdlevent.type == SDL_KEYDOWN || sdlevent.type == SDL_KEYUP) {
|
|
if (sdlevent.key.repeat != 0) { goto unknown; }
|
|
struct ENGINE_EVENT_INPUT_KB * data = engine_malloc(NULL,sizeof(struct ENGINE_EVENT_INPUT_KB));
|
|
data->pressed = (sdlevent.type == SDL_KEYDOWN);
|
|
data->key = sdlevent.key.keysym.scancode;
|
|
event->type = ENGINE_EVENT_TYPE_INPUT_KB;
|
|
event->data = data;
|
|
return event;
|
|
}
|
|
|
|
unknown:
|
|
struct ENGINE_EVENT_UNKNOWN * data = engine_malloc(NULL,sizeof(struct ENGINE_EVENT_INPUT_KB));
|
|
event->type = ENGINE_EVENT_TYPE_UNKNOWN;
|
|
event->data = data;
|
|
return event;
|
|
}
|
|
|
|
void engine_time_sleep(long long ms) {
|
|
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;
|
|
void engine_surface_color_set(char r,char g,char b,char a) {
|
|
#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
|
|
|
|
void engine_surface_draw_pixel(int x,int y) {
|
|
#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
|
|
}
|
|
|
|
void engine_window_present() {
|
|
#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
|
|
}
|
|
|
|
void engine_window_init(int width,int height,char *title) {
|
|
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)
|
|
engine_surface_color_set(0,0,0,255);
|
|
#ifdef ENGINE_SDL_SKIP_COLOR
|
|
engine_sdl_skipc_interval = 0;
|
|
engine_sdl_skipc_amount = 0;
|
|
#endif
|
|
SDL_RenderClear(engine_sdl_renderer);
|
|
#endif
|
|
}
|