Aggregate `SDL_Surface`s and their scale in `RenSurface` (#1429)
This commit is contained in:
parent
e66174f9d8
commit
71e4adbd6f
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue