fix vgcanvas_cairo_ensure_image and refactor

This commit is contained in:
lixianjing 2019-06-10 14:26:34 +08:00
parent 1335c176d7
commit 9fa41cb960
8 changed files with 53 additions and 19 deletions

View File

@ -433,6 +433,7 @@ bitmap_t* bitmap_clone(bitmap_t* bitmap) {
return_value_if_fail(b != NULL, NULL); return_value_if_fail(b != NULL, NULL);
if (b->data != NULL) { if (b->data != NULL) {
b->name = bitmap->name;
memcpy((char*)(b->data), bitmap->data, b->line_length * b->h); memcpy((char*)(b->data), bitmap->data, b->line_length * b->h);
} }

View File

@ -52,6 +52,7 @@ struct _main_loop_t {
uint32_t last_loop_time; uint32_t last_loop_time;
widget_t* wm; widget_t* wm;
canvas_t canvas; canvas_t canvas;
lcd_t* lcd;
}; };
main_loop_t* main_loop_init(int w, int h); main_loop_t* main_loop_init(int w, int h);

View File

@ -35,6 +35,7 @@ typedef struct _lcd_mem_t {
uint32_t line_length; uint32_t line_length;
bitmap_format_t format; bitmap_format_t format;
bool_t own_offline_fb;
} lcd_mem_t; } lcd_mem_t;
#define lcd_mem_set_line_length(lcd, value) ((lcd_mem_t*)lcd)->line_length = value; #define lcd_mem_set_line_length(lcd, value) ((lcd_mem_t*)lcd)->line_length = value;

View File

@ -322,18 +322,15 @@ static ret_t lcd_mem_end_frame(lcd_t* lcd) {
static ret_t lcd_mem_destroy(lcd_t* lcd) { static ret_t lcd_mem_destroy(lcd_t* lcd) {
lcd_mem_t* mem = (lcd_mem_t*)lcd; lcd_mem_t* mem = (lcd_mem_t*)lcd;
if (mem->vgcanvas) { if (mem->vgcanvas != NULL) {
vgcanvas_destroy(mem->vgcanvas); vgcanvas_destroy(mem->vgcanvas);
mem->vgcanvas = NULL; mem->vgcanvas = NULL;
} }
TKMEM_FREE(lcd);
return RET_OK; if (mem->own_offline_fb) {
} TKMEM_FREE(mem->offline_fb);
}
static ret_t lcd_mem_destroy_offline_fb(lcd_t* lcd) {
lcd_mem_t* mem = (lcd_mem_t*)lcd;
TKMEM_FREE(mem->offline_fb);
TKMEM_FREE(lcd); TKMEM_FREE(lcd);
return RET_OK; return RET_OK;
@ -369,6 +366,8 @@ static lcd_t* lcd_mem_create(wh_t w, wh_t h, bool_t alloc) {
return_value_if_fail(lcd->offline_fb != NULL, NULL); return_value_if_fail(lcd->offline_fb != NULL, NULL);
} }
lcd->own_offline_fb = alloc;
base = &(lcd->base); base = &(lcd->base);
base->begin_frame = lcd_mem_begin_frame; base->begin_frame = lcd_mem_begin_frame;
base->draw_vline = lcd_mem_draw_vline; base->draw_vline = lcd_mem_draw_vline;
@ -383,7 +382,7 @@ static lcd_t* lcd_mem_create(wh_t w, wh_t h, bool_t alloc) {
base->take_snapshot = lcd_mem_take_snapshot; base->take_snapshot = lcd_mem_take_snapshot;
base->get_desired_bitmap_format = lcd_mem_get_desired_bitmap_format; base->get_desired_bitmap_format = lcd_mem_get_desired_bitmap_format;
base->end_frame = lcd_mem_end_frame; base->end_frame = lcd_mem_end_frame;
base->destroy = alloc ? lcd_mem_destroy_offline_fb : lcd_mem_destroy; base->destroy = lcd_mem_destroy;
base->resize = lcd_mem_resize; base->resize = lcd_mem_resize;
base->flush = lcd_mem_flush; base->flush = lcd_mem_flush;
base->w = w; base->w = w;

View File

@ -124,7 +124,10 @@ static ret_t lcd_sdl2_end_frame(lcd_t* lcd) {
static ret_t lcd_sdl2_destroy(lcd_t* lcd) { static ret_t lcd_sdl2_destroy(lcd_t* lcd) {
lcd_sdl2_t* sdl = (lcd_sdl2_t*)lcd; lcd_sdl2_t* sdl = (lcd_sdl2_t*)lcd;
lcd_destroy((lcd_t*)(sdl->lcd_mem));
SDL_DestroyTexture(sdl->texture); SDL_DestroyTexture(sdl->texture);
memset(sdl, 0x00, sizeof(lcd_sdl2_t));
return RET_OK; return RET_OK;
} }
@ -161,7 +164,7 @@ static ret_t lcd_sdl2_take_snapshot(lcd_t* lcd, bitmap_t* img, bool_t auto_rotat
return lcd_take_snapshot((lcd_t*)(sdl->lcd_mem), img, auto_rotate); return lcd_take_snapshot((lcd_t*)(sdl->lcd_mem), img, auto_rotate);
} }
static ret_t lcd_sdl2_get_desired_bitmap_format(lcd_t* lcd) { static bitmap_format_t lcd_sdl2_get_desired_bitmap_format(lcd_t* lcd) {
lcd_sdl2_t* sdl = (lcd_sdl2_t*)lcd; lcd_sdl2_t* sdl = (lcd_sdl2_t*)lcd;
return lcd_get_desired_bitmap_format((lcd_t*)(sdl->lcd_mem)); return lcd_get_desired_bitmap_format((lcd_t*)(sdl->lcd_mem));

View File

@ -74,7 +74,8 @@ static ret_t main_loop_sdl_fb_create_window(main_loop_simple_t* l) {
LOOP_SDL_RENDER_SET(l, SDL_CreateRenderer(LOOP_SDL_WINDOW(l), -1, flags)); LOOP_SDL_RENDER_SET(l, SDL_CreateRenderer(LOOP_SDL_WINDOW(l), -1, flags));
return_value_if_fail(LOOP_SDL_RENDER(l) != NULL, RET_FAIL); return_value_if_fail(LOOP_SDL_RENDER(l) != NULL, RET_FAIL);
canvas_init(&(l->base.canvas), lcd_sdl2_init(LOOP_SDL_RENDER(l)), font_manager()); l->base.lcd = lcd_sdl2_init(LOOP_SDL_RENDER(l));
canvas_init(&(l->base.canvas), l->base.lcd, font_manager());
return RET_OK; return RET_OK;
} }

View File

@ -208,6 +208,7 @@ ret_t main_loop_simple_reset(main_loop_simple_t* loop) {
return_value_if_fail(loop != NULL, RET_BAD_PARAMS); return_value_if_fail(loop != NULL, RET_BAD_PARAMS);
event_queue_destroy(loop->queue); event_queue_destroy(loop->queue);
tk_mutex_destroy(loop->mutex); tk_mutex_destroy(loop->mutex);
lcd_destroy(loop->base.lcd);
memset(loop, 0x00, sizeof(main_loop_simple_t)); memset(loop, 0x00, sizeof(main_loop_simple_t));

View File

@ -26,6 +26,7 @@
#include "base/vgcanvas.h" #include "base/vgcanvas.h"
#include "cairo.h" #include "cairo.h"
#include "tkc/mem.h" #include "tkc/mem.h"
#include "tkc/darray.h"
typedef enum _cairo_source_type_t { typedef enum _cairo_source_type_t {
CAIRO_SOURCE_NONE = 0, CAIRO_SOURCE_NONE = 0,
@ -33,6 +34,7 @@ typedef enum _cairo_source_type_t {
CAIRO_SOURCE_IMAGE, CAIRO_SOURCE_IMAGE,
CAIRO_SOURCE_GRADIENT, CAIRO_SOURCE_GRADIENT,
} cairo_source_type_t; } cairo_source_type_t;
typedef struct _vgcanvas_cairo_t { typedef struct _vgcanvas_cairo_t {
vgcanvas_t base; vgcanvas_t base;
@ -42,6 +44,8 @@ typedef struct _vgcanvas_cairo_t {
cairo_source_type_t stroke_source_type; cairo_source_type_t stroke_source_type;
cairo_source_type_t fill_source_type; cairo_source_type_t fill_source_type;
darray_t images;
} vgcanvas_cairo_t; } vgcanvas_cairo_t;
ret_t vgcanvas_cairo_begin_frame(vgcanvas_t* vgcanvas, rect_t* dirty_rect) { ret_t vgcanvas_cairo_begin_frame(vgcanvas_t* vgcanvas, rect_t* dirty_rect) {
@ -426,17 +430,27 @@ static ret_t cairo_on_bitmap_destroy(bitmap_t* img) {
return RET_OK; return RET_OK;
} }
static cairo_surface_t* vgcanvas_cairo_ensure_image(bitmap_t* img) { static cairo_surface_t* vgcanvas_cairo_ensure_image(vgcanvas_cairo_t* vg, bitmap_t* img) {
cairo_surface_t* surface = (cairo_surface_t*)img->specific; cairo_surface_t* surface = NULL;
darray_t* images = &(vg->images);
bitmap_t* cairo_img = (bitmap_t*)darray_find(images, img);
if (cairo_img == NULL) {
cairo_img = bitmap_clone(img);
return_value_if_fail(cairo_img != NULL, NULL);
darray_push(images, cairo_img);
bitmap_premulti_alpha(cairo_img);
}
surface = (cairo_surface_t*)(cairo_img->specific);
if (surface == NULL) { if (surface == NULL) {
bitmap_premulti_alpha(img); surface =
surface = create_surface(img->w, img->h, img->format, (void*)(img->data)); create_surface(cairo_img->w, cairo_img->h, cairo_img->format, (void*)(cairo_img->data));
if (surface != NULL) { if (surface != NULL) {
img->specific = surface; cairo_img->specific = surface;
img->specific_ctx = NULL; cairo_img->specific_ctx = NULL;
img->specific_destroy = cairo_on_bitmap_destroy; cairo_img->specific_destroy = cairo_on_bitmap_destroy;
} }
} }
@ -450,7 +464,7 @@ static ret_t vgcanvas_cairo_draw_image(vgcanvas_t* vgcanvas, bitmap_t* img, floa
float fy = (float)dh / sh; float fy = (float)dh / sh;
float_t global_alpha = 1; float_t global_alpha = 1;
cairo_t* vg = ((vgcanvas_cairo_t*)vgcanvas)->vg; cairo_t* vg = ((vgcanvas_cairo_t*)vgcanvas)->vg;
cairo_surface_t* surface = vgcanvas_cairo_ensure_image(img); cairo_surface_t* surface = vgcanvas_cairo_ensure_image((vgcanvas_cairo_t*)vgcanvas, img);
cairo_save(vg); cairo_save(vg);
@ -608,6 +622,8 @@ static ret_t vgcanvas_cairo_destroy(vgcanvas_t* vgcanvas) {
cairo_pattern_destroy(canvas->fill_gradient); cairo_pattern_destroy(canvas->fill_gradient);
} }
darray_deinit(&(canvas->images));
return RET_OK; return RET_OK;
} }
@ -728,7 +744,7 @@ static ret_t vgcanvas_cairo_reinit(vgcanvas_t* vgcanvas, uint32_t w, uint32_t h,
static ret_t vgcanvas_cairo_paint(vgcanvas_t* vgcanvas, bool_t stroke, bitmap_t* img) { static ret_t vgcanvas_cairo_paint(vgcanvas_t* vgcanvas, bool_t stroke, bitmap_t* img) {
cairo_t* vg = ((vgcanvas_cairo_t*)vgcanvas)->vg; cairo_t* vg = ((vgcanvas_cairo_t*)vgcanvas)->vg;
cairo_surface_t* surface = vgcanvas_cairo_ensure_image(img); cairo_surface_t* surface = vgcanvas_cairo_ensure_image((vgcanvas_cairo_t*)vgcanvas, img);
cairo_set_source_surface(vg, surface, 0, 0); cairo_set_source_surface(vg, surface, 0, 0);
cairo_pattern_set_filter(cairo_get_source(vg), CAIRO_FILTER_BEST); cairo_pattern_set_filter(cairo_get_source(vg), CAIRO_FILTER_BEST);
@ -796,6 +812,16 @@ static const vgcanvas_vtable_t vt = {
.unbind_fbo = vgcanvas_cairo_unbind_fbo, .unbind_fbo = vgcanvas_cairo_unbind_fbo,
.destroy = vgcanvas_cairo_destroy}; .destroy = vgcanvas_cairo_destroy};
static int cairo_bitmap_cmp(const bitmap_t* a, bitmap_t* b) {
return_value_if_fail(a != NULL && a->name != NULL && b != NULL && b->name != NULL, -1);
if (tk_str_eq(a->name, b->name)) {
return 0;
} else {
return 1;
}
}
vgcanvas_t* vgcanvas_create(uint32_t w, uint32_t h, uint32_t stride, bitmap_format_t format, vgcanvas_t* vgcanvas_create(uint32_t w, uint32_t h, uint32_t stride, bitmap_format_t format,
void* data) { void* data) {
cairo_surface_t* surface = NULL; cairo_surface_t* surface = NULL;
@ -814,6 +840,7 @@ vgcanvas_t* vgcanvas_create(uint32_t w, uint32_t h, uint32_t stride, bitmap_form
cairo->vg = cairo_create(surface); cairo->vg = cairo_create(surface);
return_value_if_fail(cairo->vg, NULL); return_value_if_fail(cairo->vg, NULL);
darray_init(&(cairo->images), 10, (tk_destroy_t)bitmap_destroy, (tk_compare_t)cairo_bitmap_cmp);
log_debug("vgcanvas_cairo created\n"); log_debug("vgcanvas_cairo created\n");
return &(cairo->base); return &(cairo->base);