Browse Source

Render game to texture and overlay directly to renderer

master
Nathaniel Walizer 11 months ago
parent
commit
1a1fefc1a1
3 changed files with 70 additions and 87 deletions
  1. +36
    -23
      src/sdl_overlay.c
  2. +4
    -3
      src/sdl_overlay.h
  3. +30
    -61
      src/sdl_render.c

+ 36
- 23
src/sdl_overlay.c View File

@@ -25,7 +25,7 @@ uint8_t get_bits(bit_buffer* buf) {
} }


static const SDL_Color pal[2] = { static const SDL_Color pal[2] = {
{0, 0, 0}, {255, 255, 255}
{0, 0, 0, 255}, {255, 255, 255, 255}
}; };


static SDL_Surface* create_char_surface(const uint8_t* bits) { static SDL_Surface* create_char_surface(const uint8_t* bits) {
@@ -52,14 +52,26 @@ static SDL_Surface* create_char_surface(const uint8_t* bits) {
return surface; return surface;
} }


int sdl_overlay_font_init(sdl_overlay_font* font) {
static SDL_Texture* create_char_texture(SDL_Renderer* rend,
const uint8_t* bits) {
SDL_Surface* surface = create_char_surface(bits);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
SDL_Texture* texture = SDL_CreateTextureFromSurface(
rend, surface
);
SDL_FreeSurface(surface);
return texture;
}

int sdl_overlay_font_init(SDL_Renderer* rend,
sdl_overlay_font* font) {
font->chars = chars; font->chars = chars;
font->charbits = charbits; font->charbits = charbits;
font->char_count = char_count; font->char_count = char_count;
font->surfaces = calloc(char_count, sizeof(SDL_Surface*));
font->textures = calloc(char_count, sizeof(SDL_Texture*));
for (int i = 0; i < font->char_count; ++i) { for (int i = 0; i < font->char_count; ++i) {
font->surfaces[i] = create_char_surface(
&font->charbits[i * charbit_size]
font->textures[i] = create_char_texture(
rend, &font->charbits[i * charbit_size]
); );
} }
return 0; return 0;
@@ -67,7 +79,7 @@ int sdl_overlay_font_init(sdl_overlay_font* font) {


void sdl_overlay_font_done(sdl_overlay_font* font) { void sdl_overlay_font_done(sdl_overlay_font* font) {
for (int i = 0; i < font->char_count; ++i) { for (int i = 0; i < font->char_count; ++i) {
SDL_FreeSurface(font->surfaces[i]);
SDL_DestroyTexture(font->textures[i]);
} }
} }


@@ -81,34 +93,35 @@ static inline int char_index(char c) {
return 0; return 0;
} }


static void render_string(SDL_Surface* target,
int x, int y,
static void render_string(SDL_Renderer* rend, int ox, int oy,
int sx, int sy,
sdl_overlay_font* font, sdl_overlay_font* font,
const char* string) { const char* string) {
SDL_Rect rect = {
.x = x,
.y = y,
.w = char_w,
.h = char_h,
};

for (const char* c = string; *c; ++c) { for (const char* c = string; *c; ++c) {
if (*c == ' ') { if (*c == ' ') {
rect.x += (char_w / 2) - 1;
ox += ((char_w / 2) - 1);
} else { } else {
SDL_Surface* surface = font->surfaces[
char_index(*c)
];
int index = char_index(*c);
int cw = font->charbits[index * charbit_size];
SDL_Texture* texture = font->textures[index];

SDL_Rect rect = {
.x = ox * sx,
.y = oy * sy,
.w = cw * sx,
.h = char_h * sy,
};


SDL_BlitSurface(surface, NULL, target, &rect);
SDL_RenderCopy(rend, texture, NULL, &rect);


rect.x += (surface->w - 1);
ox += (cw - 1);
} }
} }
} }


int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font, int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font,
SDL_Surface* target) {
SDL_Renderer* rend,
int sx, int sy) {
int y = overlay_start_y; int y = overlay_start_y;
overlay_message* last = NULL, *next = NULL; overlay_message* last = NULL, *next = NULL;
for ( overlay_message* message = overlay->messages; for ( overlay_message* message = overlay->messages;
@@ -116,7 +129,7 @@ int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font,
last = message, message = next) { last = message, message = next) {
next = message->next; next = message->next;


render_string(target, overlay_start_x, y,
render_string(rend, overlay_start_x, y, sx, sy,
font, message->string); font, message->string);
y += (char_h + 1); y += (char_h + 1);




+ 4
- 3
src/sdl_overlay.h View File

@@ -12,15 +12,16 @@ typedef struct {
const char* chars; const char* chars;
const uint8_t* charbits; const uint8_t* charbits;
int char_count; int char_count;
SDL_Surface** surfaces;
SDL_Texture** textures;
} sdl_overlay_font; } sdl_overlay_font;




int sdl_overlay_font_init(sdl_overlay_font*);
int sdl_overlay_font_init(SDL_Renderer*, sdl_overlay_font*);


void sdl_overlay_font_done(sdl_overlay_font*); void sdl_overlay_font_done(sdl_overlay_font*);


int sdl_overlay_frame(Overlay*, sdl_overlay_font*, SDL_Surface*);
int sdl_overlay_frame(Overlay*, sdl_overlay_font*, SDL_Renderer*,
int sx, int sy);




#endif // NESE_SDL_OVERLAY_ #endif // NESE_SDL_OVERLAY_

+ 30
- 61
src/sdl_render.c View File

@@ -41,11 +41,12 @@ typedef struct {
SDL_Window* window; SDL_Window* window;
SDL_Renderer* renderer; SDL_Renderer* renderer;
SDL_Surface* background; SDL_Surface* background;
SDL_Surface* background_line;
SDL_Surface* foreground; SDL_Surface* foreground;
SDL_Surface* sprite;
SDL_Surface* target; SDL_Surface* target;
SDL_Texture* texture;
sdl_overlay_font font; sdl_overlay_font font;
int win_w;
int win_h;
} sdl_render_data; } sdl_render_data;


static sdl_render_data the_render_data = {0}; static sdl_render_data the_render_data = {0};
@@ -54,10 +55,6 @@ static sdl_render_data the_render_data = {0};
static int sdl_render_init(nes_Renderer* rend) { static int sdl_render_init(nes_Renderer* rend) {
sdl_render_data* data = &the_render_data; sdl_render_data* data = &the_render_data;


overlay_init(&rend->overlay);
// TODO: Cleanup
sdl_overlay_font_init(&data->font);

int status = SDL_Init(SDL_INIT_VIDEO); int status = SDL_Init(SDL_INIT_VIDEO);


if (0 != status) { if (0 != status) {
@@ -72,13 +69,14 @@ static int sdl_render_init(nes_Renderer* rend) {
int xscale = mode.w / nes_ppu_scan_w; int xscale = mode.w / nes_ppu_scan_w;
int scale = (xscale < yscale ? xscale : yscale); int scale = (xscale < yscale ? xscale : yscale);


data->win_w = (nes_ppu_scan_w * scale);
data->win_h = (nes_ppu_scan_h * scale);

data->window = SDL_CreateWindow( data->window = SDL_CreateWindow(
"NESe", "NESe",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
nes_ppu_scan_w * scale,
nes_ppu_scan_h * scale,
0
data->win_w, data->win_h, 0
); );
if (NULL == data->window) { if (NULL == data->window) {
fprintf(stderr, "SDL: Failed to create window\n"); fprintf(stderr, "SDL: Failed to create window\n");
@@ -94,6 +92,11 @@ static int sdl_render_init(nes_Renderer* rend) {
SDL_DestroyWindow(data->window); SDL_DestroyWindow(data->window);
SDL_Quit(); SDL_Quit();
status = -1; status = -1;

} else {
overlay_init(&rend->overlay);
// TODO: Cleanup
sdl_overlay_font_init(data->renderer, &data->font);
} }
} }


@@ -112,22 +115,6 @@ static int sdl_render_init(nes_Renderer* rend) {
} }
} }


if (0 == status) {
data->background_line = SDL_CreateRGBSurfaceWithFormat(
0, nes_ppu_render_w + 8, 8,
8, SDL_PIXELFORMAT_INDEX8
);

if (NULL == data->background_line) {
fprintf(stderr, "SDL: Failed to create block buffer\n");
SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window);
SDL_Quit();
status = -1;
}
}

if (0 == status) { if (0 == status) {
data->foreground = SDL_CreateRGBSurfaceWithFormat( data->foreground = SDL_CreateRGBSurfaceWithFormat(
0, nes_ppu_render_w, nes_ppu_render_h, 0, nes_ppu_render_w, nes_ppu_render_h,
@@ -136,7 +123,6 @@ static int sdl_render_init(nes_Renderer* rend) {


if (NULL == data->foreground) { if (NULL == data->foreground) {
fprintf(stderr, "SDL: Failed to create foreground\n"); fprintf(stderr, "SDL: Failed to create foreground\n");
SDL_FreeSurface(data->background_line);
SDL_FreeSurface(data->background); SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer); SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window); SDL_DestroyWindow(data->window);
@@ -146,36 +132,22 @@ static int sdl_render_init(nes_Renderer* rend) {
} }


if (0 == status) { if (0 == status) {
data->sprite = SDL_CreateRGBSurfaceWithFormat(
0, 8, 16, 8, SDL_PIXELFORMAT_INDEX8
data->texture = SDL_CreateTexture(
data->renderer, SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_STREAMING,
nes_ppu_render_w, nes_ppu_render_h
); );
if (NULL == data->sprite) {
fprintf(stderr, "SDL: Failed to create sprite\n");
SDL_FreeSurface(data->foreground);
SDL_FreeSurface(data->background_line);
SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window);
SDL_Quit();
status = -1;
}
}

if (0 == status) {
data->target = SDL_CreateRGBSurfaceWithFormat(
0U, nes_ppu_render_w, nes_ppu_render_h,
24U, SDL_PIXELFORMAT_RGB888
);
if (NULL == data->target) {
if (NULL == data->texture) {
fprintf(stderr, "SDL: Failed to create target\n"); fprintf(stderr, "SDL: Failed to create target\n");
SDL_FreeSurface(data->sprite);
SDL_FreeSurface(data->foreground); SDL_FreeSurface(data->foreground);
SDL_FreeSurface(data->background_line);
SDL_FreeSurface(data->background); SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer); SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window); SDL_DestroyWindow(data->window);
SDL_Quit(); SDL_Quit();
status = -1; status = -1;
} else {
SDL_LockTextureToSurface(data->texture, NULL,
&data->target);
} }
} }


@@ -188,10 +160,6 @@ static int sdl_render_init(nes_Renderer* rend) {
nes_palette, 0U, 64U); nes_palette, 0U, 64U);
SDL_SetColorKey(data->foreground, SDL_TRUE, 0xFFU); SDL_SetColorKey(data->foreground, SDL_TRUE, 0xFFU);


SDL_SetPaletteColors(data->sprite->format->palette,
nes_palette, 0U, 64U);
SDL_SetColorKey(data->sprite, SDL_TRUE, 0xFFU);

rend->data = &the_render_data; rend->data = &the_render_data;
} }


@@ -200,10 +168,8 @@ static int sdl_render_init(nes_Renderer* rend) {


static void sdl_render_done(nes_Renderer* rend) { static void sdl_render_done(nes_Renderer* rend) {
sdl_render_data* data = (sdl_render_data*)rend->data; sdl_render_data* data = (sdl_render_data*)rend->data;
SDL_FreeSurface(data->target);
SDL_FreeSurface(data->sprite);
SDL_DestroyTexture(data->texture);
SDL_FreeSurface(data->foreground); SDL_FreeSurface(data->foreground);
SDL_FreeSurface(data->background_line);
SDL_FreeSurface(data->background); SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer); SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window); SDL_DestroyWindow(data->window);
@@ -573,15 +539,18 @@ static int sdl_render(nes_Renderer* rend, nes_ppu* ppu) {
} else { } else {
REND_LOG("Scanline %3d -> Postrender\n", ppu->scanline); REND_LOG("Scanline %3d -> Postrender\n", ppu->scanline);


sdl_overlay_frame(&rend->overlay, &data->font,
data->target);
SDL_UnlockTexture(data->texture);
SDL_RenderCopy(data->renderer, data->texture, NULL, NULL);
SDL_LockTextureToSurface(data->texture, NULL,
&data->target);


SDL_Texture* texture = SDL_CreateTextureFromSurface(
data->renderer, data->target
sdl_overlay_frame(
&rend->overlay, &data->font, data->renderer,
data->win_w / nes_ppu_render_w,
data->win_h / nes_ppu_render_h
); );
SDL_RenderCopy(data->renderer, texture, NULL, NULL);
SDL_RenderPresent(data->renderer); SDL_RenderPresent(data->renderer);
SDL_DestroyTexture(texture);


status = 1; status = 1;
} }


Loading…
Cancel
Save