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