Skip to content

Commit

Permalink
Aggregate SDL_Surfaces and their scale in RenSurface (lite-xl#1429)
Browse files Browse the repository at this point in the history
  • Loading branch information
Guldoman authored Mar 19, 2023
1 parent d151083 commit 2cdf5d8
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 51 deletions.
8 changes: 5 additions & 3 deletions src/rencache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand All @@ -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);
}
}

Expand Down
31 changes: 15 additions & 16 deletions src/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
5 changes: 3 additions & 2 deletions src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
43 changes: 17 additions & 26 deletions src/renwindow.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,55 @@ 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);
}
setup_renderer(ren, w, h);
#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};
}


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
}

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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
}
6 changes: 2 additions & 4 deletions src/renwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

0 comments on commit 2cdf5d8

Please sign in to comment.