From 2cdf5d89492242084654de118016dd8cf75bd660 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 19 Mar 2023 20:39:52 +0100 Subject: [PATCH] Aggregate `SDL_Surface`s and their scale in `RenSurface` (#1429) --- src/rencache.c | 8 +++++--- src/renderer.c | 31 +++++++++++++++---------------- src/renderer.h | 5 +++-- src/renwindow.c | 43 +++++++++++++++++-------------------------- src/renwindow.h | 6 ++---- 5 files changed, 42 insertions(+), 51 deletions(-) diff --git a/src/rencache.c b/src/rencache.c index 946aa3fb..928d0b0d 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -17,6 +17,7 @@ #include #include "rencache.h" +#include "renwindow.h" /* a cache over the software renderer -- all drawing operations are stored as ** commands when issued. At the end of the frame we write the commands to a grid @@ -299,6 +300,7 @@ void rencache_end_frame(RenWindow *window_renderer) { *r = intersect_rects(*r, screen_rect); } + RenSurface rs = renwin_get_surface(window_renderer); /* redraw updated regions */ for (int i = 0; i < rect_count; i++) { /* draw */ @@ -315,18 +317,18 @@ void rencache_end_frame(RenWindow *window_renderer) { ren_set_clip_rect(window_renderer, intersect_rects(ccmd->rect, r)); break; case DRAW_RECT: - ren_draw_rect(window_renderer, rcmd->rect, rcmd->color); + ren_draw_rect(&rs, rcmd->rect, rcmd->color); break; case DRAW_TEXT: ren_font_group_set_tab_size(tcmd->fonts, tcmd->tab_size); - ren_draw_text(window_renderer, tcmd->fonts, tcmd->text, tcmd->len, tcmd->text_x, tcmd->rect.y, tcmd->color); + ren_draw_text(&rs, tcmd->fonts, tcmd->text, tcmd->len, tcmd->text_x, tcmd->rect.y, tcmd->color); break; } } if (show_debug) { RenColor color = { rand(), rand(), rand(), 50 }; - ren_draw_rect(window_renderer, r, color); + ren_draw_rect(&rs, r, color); } } diff --git a/src/renderer.c b/src/renderer.c index 226dbe71..e9e715ef 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -257,7 +257,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, #endif - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale))) goto failure; int len = strlen(path); @@ -342,7 +342,7 @@ float ren_font_group_get_size(RenFont **fonts) { } void ren_font_group_set_size(RenWindow *window_renderer, RenFont **fonts, float size) { - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) { font_clear_glyph_cache(fonts[i]); FT_Face face = fonts[i]->face; @@ -372,16 +372,16 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con break; width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance; } - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = renwin_get_surface(window_renderer).scale; return width / surface_scale; } -double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { - SDL_Surface *surface = renwin_get_surface(window_renderer); +double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { + SDL_Surface *surface = rs->surface; SDL_Rect clip; SDL_GetClipRect(surface, &clip); - const int surface_scale = renwin_surface_scale(window_renderer); + const int surface_scale = rs->scale; double pen_x = x * surface_scale; y *= surface_scale; int bytes_per_pixel = surface->format->BytesPerPixel; @@ -405,7 +405,7 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te int end_x = (metric->x1 - metric->x0) + start_x; int glyph_end = metric->x1, glyph_start = metric->x0; if (!metric->loaded && codepoint > 0xFF) - ren_draw_rect(window_renderer, (RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); + ren_draw_rect(rs, (RenRect){ start_x + 1, y, font->space_advance - 1, ren_font_group_get_height(fonts) }, color); if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) { uint8_t* source_pixels = set->surface->pixels; for (int line = metric->y0; line < metric->y1; ++line) { @@ -456,9 +456,9 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te else if(font != last || text == end) { double local_pen_x = text == end ? pen_x + adv : pen_x; if (underline) - ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(rs, (RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); if (strikethrough) - ren_draw_rect(window_renderer, (RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + ren_draw_rect(rs, (RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); last = font; last_pen_x = pen_x; } @@ -477,11 +477,11 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) { return dst; } -void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { +void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) { if (color.a == 0) { return; } - SDL_Surface *surface = renwin_get_surface(window_renderer); - const int surface_scale = renwin_surface_scale(window_renderer); + SDL_Surface *surface = rs->surface; + const int surface_scale = rs->scale; SDL_Rect dest_rect = { rect.x * surface_scale, rect.y * surface_scale, @@ -552,8 +552,7 @@ void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect) { void ren_get_size(RenWindow *window_renderer, int *x, int *y) { - const int scale = renwin_surface_scale(window_renderer); - SDL_Surface *surface = renwin_get_surface(window_renderer); - *x = surface->w / scale; - *y = surface->h / scale; + RenSurface rs = renwin_get_surface(window_renderer); + *x = rs.surface->w / rs.scale; + *y = rs.surface->h / rs.scale; } diff --git a/src/renderer.h b/src/renderer.h index 3897421e..0e96d9a9 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -19,6 +19,7 @@ typedef enum { FONT_ANTIALIASING_NONE, FONT_ANTIALIASING_GRAYSCALE, FONT_ANTIALI typedef enum { FONT_STYLE_BOLD = 1, FONT_STYLE_ITALIC = 2, FONT_STYLE_UNDERLINE = 4, FONT_STYLE_SMOOTH = 8, FONT_STYLE_STRIKETHROUGH = 16 } ERenFontStyle; typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect; +typedef struct { SDL_Surface *surface; int scale; } RenSurface; struct RenWindow; typedef struct RenWindow RenWindow; @@ -34,9 +35,9 @@ float ren_font_group_get_size(RenFont **font); void ren_font_group_set_size(RenWindow *window_renderer, RenFont **font, float size); void ren_font_group_set_tab_size(RenFont **font, int n); double ren_font_group_get_width(RenWindow *window_renderer, RenFont **font, const char *text, size_t len); -double ren_draw_text(RenWindow *window_renderer, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); +double ren_draw_text(RenSurface *rs, RenFont **font, const char *text, size_t len, float x, int y, RenColor color); -void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color); +void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color); void ren_init(SDL_Window *win); void ren_resize_window(RenWindow *window_renderer); diff --git a/src/renwindow.c b/src/renwindow.c index c700cedf..ba671404 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -24,20 +24,20 @@ static void setup_renderer(RenWindow *ren, int w, int h) { SDL_DestroyTexture(ren->texture); } ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); - ren->surface_scale = query_surface_scale(ren); + ren->rensurface.scale = query_surface_scale(ren); } #endif void renwin_init_surface(UNUSED RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER - if (ren->surface) { - SDL_FreeSurface(ren->surface); + if (ren->rensurface.surface) { + SDL_FreeSurface(ren->rensurface.surface); } int w, h; SDL_GL_GetDrawableSize(ren->window, &w, &h); - ren->surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); - if (!ren->surface) { + ren->rensurface.surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); + if (!ren->rensurface.surface) { fprintf(stderr, "Error creating surface: %s", SDL_GetError()); exit(1); } @@ -45,14 +45,6 @@ void renwin_init_surface(UNUSED RenWindow *ren) { #endif } -int renwin_surface_scale(UNUSED RenWindow *ren) { -#ifdef LITE_USE_SDL_RENDERER - return ren->surface_scale; -#else - return 1; -#endif -} - static RenRect scaled_rect(const RenRect rect, const int scale) { return (RenRect) {rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale}; @@ -60,28 +52,27 @@ static RenRect scaled_rect(const RenRect rect, const int scale) { void renwin_clip_to_surface(RenWindow *ren) { - SDL_Surface *surface = renwin_get_surface(ren); - SDL_SetClipRect(surface, NULL); + SDL_SetClipRect(renwin_get_surface(ren).surface, NULL); } void renwin_set_clip_rect(RenWindow *ren, RenRect rect) { - SDL_Surface *surface = renwin_get_surface(ren); - RenRect sr = scaled_rect(rect, renwin_surface_scale(ren)); - SDL_SetClipRect(surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); + RenSurface rs = renwin_get_surface(ren); + RenRect sr = scaled_rect(rect, rs.scale); + SDL_SetClipRect(rs.surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); } -SDL_Surface *renwin_get_surface(RenWindow *ren) { +RenSurface renwin_get_surface(RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER - return ren->surface; + return ren->rensurface; #else SDL_Surface *surface = SDL_GetWindowSurface(ren->window); if (!surface) { fprintf(stderr, "Error getting window surface: %s", SDL_GetError()); exit(1); } - return surface; + return (RenSurface){.surface = surface, .scale = 1}; #endif } @@ -90,7 +81,7 @@ void renwin_resize_surface(UNUSED RenWindow *ren) { int new_w, new_h; SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h); /* Note that (w, h) may differ from (new_w, new_h) on retina displays. */ - if (new_w != ren->surface->w || new_h != ren->surface->h) { + if (new_w != ren->rensurface.surface->w || new_h != ren->rensurface.surface->h) { renwin_init_surface(ren); renwin_clip_to_surface(ren); setup_renderer(ren, new_w, new_h); @@ -104,14 +95,14 @@ void renwin_show_window(RenWindow *ren) { void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) { #ifdef LITE_USE_SDL_RENDERER - const int scale = ren->surface_scale; + const int scale = ren->rensurface.scale; for (int i = 0; i < count; i++) { const RenRect *r = &rects[i]; const int x = scale * r->x, y = scale * r->y; const int w = scale * r->width, h = scale * r->height; const SDL_Rect sr = {.x = x, .y = y, .w = w, .h = h}; - int32_t *pixels = ((int32_t *) ren->surface->pixels) + x + ren->surface->w * y; - SDL_UpdateTexture(ren->texture, &sr, pixels, ren->surface->w * 4); + int32_t *pixels = ((int32_t *) ren->rensurface.surface->pixels) + x + ren->rensurface.surface->w * y; + SDL_UpdateTexture(ren->texture, &sr, pixels, ren->rensurface.surface->w * 4); } SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL); SDL_RenderPresent(ren->renderer); @@ -126,6 +117,6 @@ void renwin_free(RenWindow *ren) { #ifdef LITE_USE_SDL_RENDERER SDL_DestroyTexture(ren->texture); SDL_DestroyRenderer(ren->renderer); - SDL_FreeSurface(ren->surface); + SDL_FreeSurface(ren->rensurface.surface); #endif } diff --git a/src/renwindow.h b/src/renwindow.h index 7f08aa2f..6b0b9eaa 100644 --- a/src/renwindow.h +++ b/src/renwindow.h @@ -6,19 +6,17 @@ struct RenWindow { #ifdef LITE_USE_SDL_RENDERER SDL_Renderer *renderer; SDL_Texture *texture; - SDL_Surface *surface; - int surface_scale; + RenSurface rensurface; #endif }; typedef struct RenWindow RenWindow; void renwin_init_surface(RenWindow *ren); -int renwin_surface_scale(RenWindow *ren); void renwin_clip_to_surface(RenWindow *ren); void renwin_set_clip_rect(RenWindow *ren, RenRect rect); void renwin_resize_surface(RenWindow *ren); void renwin_show_window(RenWindow *ren); void renwin_update_rects(RenWindow *ren, RenRect *rects, int count); void renwin_free(RenWindow *ren); -SDL_Surface *renwin_get_surface(RenWindow *ren); +RenSurface renwin_get_surface(RenWindow *ren);