vxKernel/src/driver/mpu/x86/sdl2/window.c

140 lines
2.8 KiB
C

#include <SDL2/SDL.h>
#include <vhex/display.h>
#include <vhex/display/interface.h>
#include <vhex/driver.h>
/* Literal error message printed to stderr, evaluates to 1 for a combined
return/exit() call */
#define err(fmt, ...) ({ \
fprintf(stderr, "error: " fmt "\n", ##__VA_ARGS__); \
1; \
})
static SDL_Window *__sdl_window = NULL;
__attribute__((destructor))
void quit(void)
{
if(__sdl_window != NULL) {
SDL_DestroyWindow(__sdl_window);
__sdl_window = NULL;
}
}
//---
// Driver primitives
//---
uint32_t vhex_vram[(396*224) / 2];
/* sdl_frame_start() - prepar the screen and reset surfaces */
int sdl_frame_start(dsurface_t *surface)
{
surface->vram = (void*)vhex_vram;
surface->width = 396;
surface->height = 224;
surface->x1 = 0;
surface->y1 = 0;
surface->x2 = 395;
surface->y2 = 223;
return (0);
}
/* sdl_frame_frag_next() : update the next fragment */
int sdl_frame_frag_next(dsurface_t *surface)
{
(void)surface;
return -1;
}
/* sdl_frame_frag_send() : send fragment to the screen */
int sdl_frame_frag_send(dsurface_t *surface)
{
SDL_SetWindowSize(__sdl_window, 396, 224);
SDL_Surface *src = SDL_CreateRGBSurface(
0, 396, 224, 24,
0x000000ff, 0x0000ff00, 0x0000ff00, 0
);
uint16_t *vram = surface->vram;
uint8_t *display = src->pixels;
for (int i = 0; i < 396 * 224; ++i){
display[(i * 3) + 0] = (((vram[i] & 0xf800) >> 11) * 255) / 31;
display[(i * 3) + 1] = (((vram[i] & 0x07e0) >> 5) * 255) / 63;
display[(i * 3) + 2] = (((vram[i] & 0x001f) >> 0) * 255) / 31;
}
SDL_Surface *dst = SDL_GetWindowSurface(__sdl_window);
SDL_BlitSurface(src, NULL, dst, NULL);
SDL_FreeSurface(src);
SDL_UpdateWindowSurface(__sdl_window);
return 0;
}
/* sdl_frame_end() : destructor */
int sdl_frame_end(dsurface_t *surface)
{
(void)surface;
return 0;
}
//---
// Driver context management
//---
static int __sdl_configure(void)
{
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
int rc = SDL_Init(SDL_INIT_VIDEO);
if(rc < 0)
return err("Cannot initialize SDL: %s\n", SDL_GetError());
}
__sdl_window = SDL_CreateWindow(
"vxKernel",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
396,
224,
0
);
return 0;
}
static void __sdl_hsave(void)
{
// Nothing to do, this is a fake driver
;
}
static void __sdl_hrestore(void)
{
// Nothing to do, this is a fake driver
;
}
struct vhex_driver drv_sdl = {
.name = "SDL",
.hsave = (void*)&__sdl_hsave,
.hrestore = (void*)&__sdl_hrestore,
.configure = (void*)&__sdl_configure,
.state_size = 4,
.flags = {
.DISPLAY = 1,
.SHARED = 0,
.UNUSED = 0,
},
.module_data = &(struct dstack_drv_interface){
.frame_start = &sdl_frame_start,
.frame_frag_next = &sdl_frame_frag_next,
.frame_frag_send = &sdl_frame_frag_send,
.frame_end = &sdl_frame_end,
.display_width = 396,
.display_height = 224
}
};
VHEX_DECLARE_DRIVER(16, drv_sdl);