Aggregate `SDL_Surface`s and their scale in `RenSurface` (#1429)

This commit is contained in:
Guldoman 2023-03-19 20:39:52 +01:00 committed by George Sokianos
parent 3739bf0186
commit 1d86665b6d
5 changed files with 42 additions and 51 deletions

View File

@ -17,6 +17,7 @@
#include <lauxlib.h> #include <lauxlib.h>
#include "rencache.h" #include "rencache.h"
#include "renwindow.h"
/* a cache over the software renderer -- all drawing operations are stored as /* 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 ** 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); *r = intersect_rects(*r, screen_rect);
} }
RenSurface rs = renwin_get_surface(window_renderer);
/* redraw updated regions */ /* redraw updated regions */
for (int i = 0; i < rect_count; i++) { for (int i = 0; i < rect_count; i++) {
/* draw */ /* draw */
@ -315,18 +317,18 @@ void rencache_end_frame(RenWindow *window_renderer) {
ren_set_clip_rect(window_renderer, intersect_rects(ccmd->rect, r)); ren_set_clip_rect(window_renderer, intersect_rects(ccmd->rect, r));
break; break;
case DRAW_RECT: case DRAW_RECT:
ren_draw_rect(window_renderer, rcmd->rect, rcmd->color); ren_draw_rect(&rs, rcmd->rect, rcmd->color);
break; break;
case DRAW_TEXT: case DRAW_TEXT:
ren_font_group_set_tab_size(tcmd->fonts, tcmd->tab_size); 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; break;
} }
} }
if (show_debug) { if (show_debug) {
RenColor color = { rand(), rand(), rand(), 50 }; RenColor color = { rand(), rand(), rand(), 50 };
ren_draw_rect(window_renderer, r, color); ren_draw_rect(&rs, r, color);
} }
} }

View File

@ -257,7 +257,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size,
#endif #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))) if (FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale)))
goto failure; goto failure;
int len = strlen(path); 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) { 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) { for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
font_clear_glyph_cache(fonts[i]); font_clear_glyph_cache(fonts[i]);
FT_Face face = fonts[i]->face; FT_Face face = fonts[i]->face;
@ -372,16 +372,16 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con
break; break;
width += (!font || metric->xadvance) ? metric->xadvance : fonts[0]->space_advance; 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; 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) { double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) {
SDL_Surface *surface = renwin_get_surface(window_renderer); SDL_Surface *surface = rs->surface;
SDL_Rect clip; SDL_Rect clip;
SDL_GetClipRect(surface, &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; double pen_x = x * surface_scale;
y *= surface_scale; y *= surface_scale;
int bytes_per_pixel = surface->format->BytesPerPixel; 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 end_x = (metric->x1 - metric->x0) + start_x;
int glyph_end = metric->x1, glyph_start = metric->x0; int glyph_end = metric->x1, glyph_start = metric->x0;
if (!metric->loaded && codepoint > 0xFF) 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) { if (set->surface && color.a > 0 && end_x >= clip.x && start_x < clip_end_x) {
uint8_t* source_pixels = set->surface->pixels; uint8_t* source_pixels = set->surface->pixels;
for (int line = metric->y0; line < metric->y1; ++line) { 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) { else if(font != last || text == end) {
double local_pen_x = text == end ? pen_x + adv : pen_x; double local_pen_x = text == end ? pen_x + adv : pen_x;
if (underline) 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) 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 = font;
last_pen_x = pen_x; last_pen_x = pen_x;
} }
@ -477,11 +477,11 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) {
return dst; 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; } if (color.a == 0) { return; }
SDL_Surface *surface = renwin_get_surface(window_renderer); SDL_Surface *surface = rs->surface;
const int surface_scale = renwin_surface_scale(window_renderer); const int surface_scale = rs->scale;
SDL_Rect dest_rect = { rect.x * surface_scale, SDL_Rect dest_rect = { rect.x * surface_scale,
rect.y * 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) { void ren_get_size(RenWindow *window_renderer, int *x, int *y) {
const int scale = renwin_surface_scale(window_renderer); RenSurface rs = renwin_get_surface(window_renderer);
SDL_Surface *surface = renwin_get_surface(window_renderer); *x = rs.surface->w / rs.scale;
*x = surface->w / scale; *y = rs.surface->h / rs.scale;
*y = surface->h / scale;
} }

View File

@ -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 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 { uint8_t b, g, r, a; } RenColor;
typedef struct { int x, y, width, height; } RenRect; typedef struct { int x, y, width, height; } RenRect;
typedef struct { SDL_Surface *surface; int scale; } RenSurface;
struct RenWindow; struct RenWindow;
typedef struct RenWindow 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_size(RenWindow *window_renderer, RenFont **font, float size);
void ren_font_group_set_tab_size(RenFont **font, int n); 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_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_init(SDL_Window *win);
void ren_resize_window(RenWindow *window_renderer); void ren_resize_window(RenWindow *window_renderer);

View File

@ -24,20 +24,20 @@ static void setup_renderer(RenWindow *ren, int w, int h) {
SDL_DestroyTexture(ren->texture); SDL_DestroyTexture(ren->texture);
} }
ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); 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 #endif
void renwin_init_surface(UNUSED RenWindow *ren) { void renwin_init_surface(UNUSED RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
if (ren->surface) { if (ren->rensurface.surface) {
SDL_FreeSurface(ren->surface); SDL_FreeSurface(ren->rensurface.surface);
} }
int w, h; int w, h;
SDL_GL_GetDrawableSize(ren->window, &w, &h); SDL_GL_GetDrawableSize(ren->window, &w, &h);
ren->surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); ren->rensurface.surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32);
if (!ren->surface) { if (!ren->rensurface.surface) {
fprintf(stderr, "Error creating surface: %s", SDL_GetError()); fprintf(stderr, "Error creating surface: %s", SDL_GetError());
exit(1); exit(1);
} }
@ -45,14 +45,6 @@ void renwin_init_surface(UNUSED RenWindow *ren) {
#endif #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) { static RenRect scaled_rect(const RenRect rect, const int scale) {
return (RenRect) {rect.x * scale, rect.y * scale, rect.width * scale, rect.height * 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) { void renwin_clip_to_surface(RenWindow *ren) {
SDL_Surface *surface = renwin_get_surface(ren); SDL_SetClipRect(renwin_get_surface(ren).surface, NULL);
SDL_SetClipRect(surface, NULL);
} }
void renwin_set_clip_rect(RenWindow *ren, RenRect rect) { void renwin_set_clip_rect(RenWindow *ren, RenRect rect) {
SDL_Surface *surface = renwin_get_surface(ren); RenSurface rs = renwin_get_surface(ren);
RenRect sr = scaled_rect(rect, renwin_surface_scale(ren)); RenRect sr = scaled_rect(rect, rs.scale);
SDL_SetClipRect(surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height}); 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 #ifdef LITE_USE_SDL_RENDERER
return ren->surface; return ren->rensurface;
#else #else
SDL_Surface *surface = SDL_GetWindowSurface(ren->window); SDL_Surface *surface = SDL_GetWindowSurface(ren->window);
if (!surface) { if (!surface) {
fprintf(stderr, "Error getting window surface: %s", SDL_GetError()); fprintf(stderr, "Error getting window surface: %s", SDL_GetError());
exit(1); exit(1);
} }
return surface; return (RenSurface){.surface = surface, .scale = 1};
#endif #endif
} }
@ -90,7 +81,7 @@ void renwin_resize_surface(UNUSED RenWindow *ren) {
int new_w, new_h; int new_w, new_h;
SDL_GL_GetDrawableSize(ren->window, &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. */ /* 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_init_surface(ren);
renwin_clip_to_surface(ren); renwin_clip_to_surface(ren);
setup_renderer(ren, new_w, new_h); 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) { void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) {
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
const int scale = ren->surface_scale; const int scale = ren->rensurface.scale;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const RenRect *r = &rects[i]; const RenRect *r = &rects[i];
const int x = scale * r->x, y = scale * r->y; const int x = scale * r->x, y = scale * r->y;
const int w = scale * r->width, h = scale * r->height; const int w = scale * r->width, h = scale * r->height;
const SDL_Rect sr = {.x = x, .y = y, .w = w, .h = h}; 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; int32_t *pixels = ((int32_t *) ren->rensurface.surface->pixels) + x + ren->rensurface.surface->w * y;
SDL_UpdateTexture(ren->texture, &sr, pixels, ren->surface->w * 4); SDL_UpdateTexture(ren->texture, &sr, pixels, ren->rensurface.surface->w * 4);
} }
SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL); SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL);
SDL_RenderPresent(ren->renderer); SDL_RenderPresent(ren->renderer);
@ -126,6 +117,6 @@ void renwin_free(RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
SDL_DestroyTexture(ren->texture); SDL_DestroyTexture(ren->texture);
SDL_DestroyRenderer(ren->renderer); SDL_DestroyRenderer(ren->renderer);
SDL_FreeSurface(ren->surface); SDL_FreeSurface(ren->rensurface.surface);
#endif #endif
} }

View File

@ -6,19 +6,17 @@ struct RenWindow {
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *texture; SDL_Texture *texture;
SDL_Surface *surface; RenSurface rensurface;
int surface_scale;
#endif #endif
}; };
typedef struct RenWindow RenWindow; typedef struct RenWindow RenWindow;
void renwin_init_surface(RenWindow *ren); void renwin_init_surface(RenWindow *ren);
int renwin_surface_scale(RenWindow *ren);
void renwin_clip_to_surface(RenWindow *ren); void renwin_clip_to_surface(RenWindow *ren);
void renwin_set_clip_rect(RenWindow *ren, RenRect rect); void renwin_set_clip_rect(RenWindow *ren, RenRect rect);
void renwin_resize_surface(RenWindow *ren); void renwin_resize_surface(RenWindow *ren);
void renwin_show_window(RenWindow *ren); void renwin_show_window(RenWindow *ren);
void renwin_update_rects(RenWindow *ren, RenRect *rects, int count); void renwin_update_rects(RenWindow *ren, RenRect *rects, int count);
void renwin_free(RenWindow *ren); void renwin_free(RenWindow *ren);
SDL_Surface *renwin_get_surface(RenWindow *ren); RenSurface renwin_get_surface(RenWindow *ren);