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 e66174f9d8
commit 71e4adbd6f
5 changed files with 42 additions and 51 deletions

View File

@ -17,6 +17,7 @@
#include <lauxlib.h>
#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);
}
}

View File

@ -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,
@ -553,8 +553,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;
}

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

View File

@ -36,20 +36,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);
}
@ -57,14 +57,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};
@ -72,28 +64,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
}
@ -102,7 +93,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);
@ -116,14 +107,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);
@ -138,7 +129,7 @@ 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
}

View File

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