diff --git a/src/sdl_overlay.c b/src/sdl_overlay.c index 95ce8a1..00416f2 100644 --- a/src/sdl_overlay.c +++ b/src/sdl_overlay.c @@ -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); diff --git a/src/sdl_overlay.h b/src/sdl_overlay.h index 6e3f39f..594c835 100644 --- a/src/sdl_overlay.h +++ b/src/sdl_overlay.h @@ -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_ diff --git a/src/sdl_render.c b/src/sdl_render.c index 00acb3b..48efbb5 100644 --- a/src/sdl_render.c +++ b/src/sdl_render.c @@ -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; }