mirror of
https://github.com/jtheoof/swappy.git
synced 2024-08-16 18:20:45 +03:00
perf(render): improve rendering for scaled surfaces
This commit is contained in:
parent
f405d5a473
commit
0e9f66ad5b
@ -12,4 +12,6 @@ bool buffer_init_from_file(struct swappy_state *state);
|
||||
|
||||
bool buffer_parse_geometry(struct swappy_state *state);
|
||||
|
||||
void buffer_resize_patterns(struct swappy_state *state);
|
||||
|
||||
void buffer_free_all(struct swappy_state *state);
|
||||
|
@ -196,7 +196,10 @@ struct swappy_state {
|
||||
struct swappy_config *config;
|
||||
struct swappy_wayland *wl;
|
||||
|
||||
cairo_surface_t *cairo_surface;
|
||||
cairo_surface_t *original_image_surface;
|
||||
cairo_surface_t *scaled_image_surface;
|
||||
cairo_surface_t *rendered_surface;
|
||||
|
||||
GList *patterns; // List of cairo_pattern_t
|
||||
|
||||
enum swappy_paint_type mode;
|
||||
@ -208,6 +211,9 @@ struct swappy_state {
|
||||
|
||||
struct swappy_box *window;
|
||||
struct swappy_box *geometry;
|
||||
|
||||
cairo_rectangle_int_t *drawing_area_rect;
|
||||
|
||||
gint scaling_factor;
|
||||
|
||||
GList *paints;
|
||||
|
@ -13,13 +13,6 @@
|
||||
#include "swappy.h"
|
||||
#include "wayland.h"
|
||||
|
||||
static void on_area_size_allocate(GtkWidget *area, struct swappy_state *state) {
|
||||
GtkAllocation *alloc = g_new(GtkAllocation, 1);
|
||||
gtk_widget_get_allocation(area, alloc);
|
||||
g_info("size of area to render: %ux%u", alloc->width, alloc->height);
|
||||
g_free(alloc);
|
||||
}
|
||||
|
||||
static void update_ui_undo_redo(struct swappy_state *state) {
|
||||
GtkWidget *undo = GTK_WIDGET(state->ui->undo);
|
||||
GtkWidget *redo = GTK_WIDGET(state->ui->redo);
|
||||
@ -237,7 +230,10 @@ void blur_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
|
||||
void application_finish(struct swappy_state *state) {
|
||||
paint_free_all(state);
|
||||
buffer_free_all(state);
|
||||
cairo_surface_destroy(state->cairo_surface);
|
||||
g_free(state->drawing_area_rect);
|
||||
cairo_surface_destroy(state->rendered_surface);
|
||||
cairo_surface_destroy(state->original_image_surface);
|
||||
cairo_surface_destroy(state->scaled_image_surface);
|
||||
g_free(state->file_str);
|
||||
g_free(state->geometry_str);
|
||||
g_free(state->geometry);
|
||||
@ -382,7 +378,7 @@ void redo_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
|
||||
|
||||
gboolean draw_area_handler(GtkWidget *widget, cairo_t *cr,
|
||||
struct swappy_state *state) {
|
||||
cairo_set_source_surface(cr, state->cairo_surface, 0, 0);
|
||||
cairo_set_source_surface(cr, state->rendered_surface, 0, 0);
|
||||
cairo_paint(cr);
|
||||
|
||||
return FALSE;
|
||||
@ -392,19 +388,26 @@ gboolean draw_area_configure_handler(GtkWidget *widget,
|
||||
GdkEventConfigure *event,
|
||||
struct swappy_state *state) {
|
||||
g_debug("received configure_event handler");
|
||||
cairo_surface_destroy(state->cairo_surface);
|
||||
cairo_surface_destroy(state->rendered_surface);
|
||||
g_free(state->drawing_area_rect);
|
||||
|
||||
cairo_surface_t *surface = gdk_window_create_similar_surface(
|
||||
gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR_ALPHA,
|
||||
gtk_widget_get_allocated_width(widget),
|
||||
gtk_widget_get_allocated_height(widget));
|
||||
|
||||
state->rendered_surface = surface;
|
||||
|
||||
GtkAllocation *alloc = g_new(GtkAllocation, 1);
|
||||
gtk_widget_get_allocation(widget, alloc);
|
||||
state->drawing_area_rect = alloc;
|
||||
buffer_resize_patterns(state);
|
||||
|
||||
g_info("size of cairo_surface: %ux%u with type: %d",
|
||||
cairo_image_surface_get_width(surface),
|
||||
cairo_image_surface_get_height(surface),
|
||||
cairo_image_surface_get_format(surface));
|
||||
|
||||
state->cairo_surface = surface;
|
||||
g_info("size of area to render: %ux%u", alloc->width, alloc->height);
|
||||
|
||||
render_state(state);
|
||||
|
||||
@ -656,9 +659,6 @@ static bool load_layout(struct swappy_state *state) {
|
||||
state->ui->area = area;
|
||||
state->ui->window = window;
|
||||
|
||||
g_signal_connect(area, "size-allocate", G_CALLBACK(on_area_size_allocate),
|
||||
state);
|
||||
|
||||
compute_window_size(state);
|
||||
|
||||
gtk_widget_set_size_request(area, state->window->width,
|
||||
|
43
src/buffer.c
43
src/buffer.c
@ -275,8 +275,7 @@ bool buffer_init_from_file(struct swappy_state *state) {
|
||||
|
||||
cairo_pattern_t *output_pattern = cairo_pattern_create_for_surface(surface);
|
||||
state->patterns = g_list_append(state->patterns, output_pattern);
|
||||
|
||||
cairo_surface_destroy(surface);
|
||||
state->original_image_surface = surface;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -294,6 +293,46 @@ bool buffer_parse_geometry(struct swappy_state *state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void scale_pattern(gpointer data, gpointer user_data) {
|
||||
struct swappy_state *state = (struct swappy_state *)user_data;
|
||||
cairo_pattern_t *pattern = (cairo_pattern_t *)data;
|
||||
int image_width, image_height;
|
||||
int rendered_width, rendered_height;
|
||||
|
||||
image_width = state->geometry->width;
|
||||
image_height = state->geometry->height;
|
||||
|
||||
rendered_width = state->drawing_area_rect->width;
|
||||
rendered_height = state->drawing_area_rect->height;
|
||||
|
||||
cairo_surface_t *scaled = cairo_surface_create_similar(
|
||||
state->rendered_surface, CAIRO_CONTENT_COLOR_ALPHA, rendered_width,
|
||||
rendered_height);
|
||||
cairo_t *cr = cairo_create(scaled);
|
||||
|
||||
double sx = (double)rendered_width / image_width;
|
||||
double sy = (double)rendered_height / image_height;
|
||||
|
||||
cairo_matrix_t matrix;
|
||||
cairo_matrix_init_scale(&matrix, 1.0 / sx, 1.0 / sy);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_set_source_surface(cr, state->original_image_surface, 0, 0);
|
||||
cairo_set_source(cr, pattern);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_destroy(cr);
|
||||
|
||||
if (state->scaled_image_surface) {
|
||||
cairo_surface_destroy(state->scaled_image_surface);
|
||||
}
|
||||
|
||||
state->scaled_image_surface = scaled;
|
||||
}
|
||||
|
||||
void buffer_resize_patterns(struct swappy_state *state) {
|
||||
g_list_foreach(state->patterns, scale_pattern, state);
|
||||
}
|
||||
|
||||
void buffer_wayland_destroy(struct swappy_buffer *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
|
@ -6,10 +6,10 @@
|
||||
#include "notification.h"
|
||||
|
||||
GdkPixbuf *pixbuf_get_from_state(struct swappy_state *state) {
|
||||
guint width = cairo_image_surface_get_width(state->cairo_surface);
|
||||
guint height = cairo_image_surface_get_height(state->cairo_surface);
|
||||
guint width = cairo_image_surface_get_width(state->rendered_surface);
|
||||
guint height = cairo_image_surface_get_height(state->rendered_surface);
|
||||
GdkPixbuf *pixbuf =
|
||||
gdk_pixbuf_get_from_surface(state->cairo_surface, 0, 0, width, height);
|
||||
gdk_pixbuf_get_from_surface(state->rendered_surface, 0, 0, width, height);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
40
src/render.c
40
src/render.c
@ -335,29 +335,6 @@ static void render_shape(cairo_t *cr, struct swappy_paint_shape shape) {
|
||||
cairo_restore(cr);
|
||||
}
|
||||
|
||||
static void render_buffers(cairo_t *cr, struct swappy_state *state) {
|
||||
if (!state->patterns) {
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_save(cr);
|
||||
|
||||
double sx = (double)state->window->width / state->geometry->width;
|
||||
double sy = (double)state->window->height / state->geometry->height;
|
||||
|
||||
// g_debug("scaling cairo context: (%.2lf, %.2lf)", sx, sy);
|
||||
|
||||
cairo_scale(cr, sx, sy);
|
||||
|
||||
for (GList *elem = state->patterns; elem; elem = elem->prev) {
|
||||
cairo_pattern_t *pattern = elem->data;
|
||||
cairo_set_source(cr, pattern);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
cairo_restore(cr);
|
||||
}
|
||||
|
||||
static void render_background(cairo_t *cr, struct swappy_state *state) {
|
||||
cairo_set_source_rgb(cr, 0, 0, 0);
|
||||
cairo_paint(cr);
|
||||
@ -434,6 +411,19 @@ static void render_brush(cairo_t *cr, struct swappy_paint_brush brush) {
|
||||
}
|
||||
}
|
||||
|
||||
static void render_image(cairo_t *cr, struct swappy_state *state) {
|
||||
cairo_surface_t *surface = state->scaled_image_surface;
|
||||
|
||||
cairo_save(cr);
|
||||
|
||||
if (surface && !cairo_surface_status(surface)) {
|
||||
cairo_set_source_surface(cr, surface, 0, 0);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
cairo_restore(cr);
|
||||
}
|
||||
|
||||
static void render_paint(cairo_t *cr, struct swappy_paint *paint) {
|
||||
if (!paint->can_draw) {
|
||||
return;
|
||||
@ -471,11 +461,11 @@ static void render_paints(cairo_t *cr, struct swappy_state *state) {
|
||||
}
|
||||
|
||||
void render_state(struct swappy_state *state) {
|
||||
cairo_surface_t *surface = state->cairo_surface;
|
||||
cairo_surface_t *surface = state->rendered_surface;
|
||||
cairo_t *cr = cairo_create(surface);
|
||||
|
||||
render_background(cr, state);
|
||||
render_buffers(cr, state);
|
||||
render_image(cr, state);
|
||||
render_paints(cr, state);
|
||||
|
||||
cairo_destroy(cr);
|
||||
|
Loading…
Reference in New Issue
Block a user