Bläddra i källkod

Render game to texture and overlay directly to renderer

master
Nathaniel Walizer 11 månader sedan
förälder
incheckning
1a1fefc1a1
3 ändrade filer med 70 tillägg och 87 borttagningar
  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 Visa fil

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

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) {
@@ -52,14 +52,26 @@ static SDL_Surface* create_char_surface(const uint8_t* bits) {
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->charbits = charbits;
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) {
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;
@@ -67,7 +79,7 @@ int sdl_overlay_font_init(sdl_overlay_font* font) {

void sdl_overlay_font_done(sdl_overlay_font* font) {
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;
}

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,
const char* string) {
SDL_Rect rect = {
.x = x,
.y = y,
.w = char_w,
.h = char_h,
};

for (const char* c = string; *c; ++c) {
if (*c == ' ') {
rect.x += (char_w / 2) - 1;
ox += ((char_w / 2) - 1);
} 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,
SDL_Surface* target) {
SDL_Renderer* rend,
int sx, int sy) {
int y = overlay_start_y;
overlay_message* last = NULL, *next = NULL;
for ( overlay_message* message = overlay->messages;
@@ -116,7 +129,7 @@ int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font,
last = message, message = next) {
next = message->next;

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



+ 4
- 3
src/sdl_overlay.h Visa fil

@@ -12,15 +12,16 @@ typedef struct {
const char* chars;
const uint8_t* charbits;
int char_count;
SDL_Surface** surfaces;
SDL_Texture** textures;
} 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*);

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_

+ 30
- 61
src/sdl_render.c Visa fil

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

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) {
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);

if (0 != status) {
@@ -72,13 +69,14 @@ static int sdl_render_init(nes_Renderer* rend) {
int xscale = mode.w / nes_ppu_scan_w;
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(
"NESe",
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) {
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_Quit();
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) {
data->foreground = SDL_CreateRGBSurfaceWithFormat(
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) {
fprintf(stderr, "SDL: Failed to create foreground\n");
SDL_FreeSurface(data->background_line);
SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window);
@@ -146,36 +132,22 @@ static int sdl_render_init(nes_Renderer* rend) {
}

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");
SDL_FreeSurface(data->sprite);
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;
} else {
SDL_LockTextureToSurface(data->texture, NULL,
&data->target);
}
}

@@ -188,10 +160,6 @@ static int sdl_render_init(nes_Renderer* rend) {
nes_palette, 0U, 64U);
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;
}

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

static void sdl_render_done(nes_Renderer* rend) {
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->background_line);
SDL_FreeSurface(data->background);
SDL_DestroyRenderer(data->renderer);
SDL_DestroyWindow(data->window);
@@ -573,15 +539,18 @@ static int sdl_render(nes_Renderer* rend, nes_ppu* ppu) {
} else {
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_DestroyTexture(texture);

status = 1;
}


Laddar…
Avbryt
Spara