1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

Draw: make ready to use hw. accelerator

This commit is contained in:
Kiss-Vamosi Gabor 2017-06-16 22:30:40 +02:00
parent 752a7aa7b5
commit 2b6b3aec91
2 changed files with 135 additions and 131 deletions

View File

@ -346,83 +346,70 @@ void lv_draw_img(const area_t * cords_p, const area_t * mask_p,
uint32_t br;
res = fs_read(&file, &header, sizeof(lv_img_raw_header_t), &br);
/*If the width is greater then map width then it is upscaled */
/*If the width is greater then real img. width then it is upscaled */
bool upscale = false;
if(area_get_width(cords_p) > header.w) upscale = true;
cord_t row;
area_t act_area;
area_t mask_sub;
area_t mask_com; /*Common area of mask and cords*/
bool union_ok;
union_ok = area_union(&mask_sub, mask_p, cords_p);
union_ok = area_union(&mask_com, mask_p, cords_p);
if(union_ok == false) {
fs_close(&file);
return;
}
uint8_t ds_shift = 0;
uint8_t ds_num = 1;
/*Set some values if upscale enabled*/
if(upscale != false) {
ds_shift = 1;
ds_num = 2;
}
uint32_t start_offset = sizeof(lv_img_raw_header_t);
start_offset += (area_get_width(cords_p) >> ds_shift) *
((mask_sub.y1 - cords_p->y1) >> ds_shift) * sizeof(color_t); /*First row*/
start_offset += ((mask_sub.x1 - cords_p->x1) >> ds_shift) * sizeof(color_t); /*First col*/
fs_seek(&file, start_offset);
uint32_t useful_data = (area_get_width(&mask_sub) >> ds_shift) * sizeof(color_t);
uint32_t next_row = (area_get_width(cords_p) >> ds_shift) * sizeof(color_t) - useful_data;
/*Round the coordinates with upscale*/
if(upscale != false) {
if((mask_sub.x1 & 0x1) != 0) mask_sub.x1 -= 1; /*Can be only even*/
if((mask_sub.x2 & 0x1) == 0) mask_sub.x2 -= 1; /*Can be only odd*/
if((mask_com.x1 & 0x1) != 0) mask_com.x1 -= 1; /*Can be only even*/
if((mask_com.x2 & 0x1) == 0) mask_com.x2 -= 1; /*Can be only odd*/
}
area_cpy(&act_area, &mask_sub);
/* Round down the start coordinate, because the upscaled images
* can start only LV_DOWNSCALE 'y' coordinates */
act_area.y1 &= ~(cord_t)(ds_num - 1) ;
act_area.y2 = act_area.y1 + ds_num - 1;
uint32_t act_pos;
bool const_data = false;
/*If the img. data is inside the MCU then do not use FS reading just a pointer*/
if(fn[0] == UFS_LETTER) {
if(((ufs_file_t*)file.file_d)->ent->const_data != 0) {
const_data = true;
}
uint8_t * f_data = ((ufs_file_t*)file.file_d)->ent->data_d;
f_data += sizeof(lv_img_raw_header_t);
map_fp(cords_p, &mask_com, (void*)f_data , style->opa, header.transp, upscale, style->ccolor, style->img_recolor);
}
for(row = mask_sub.y1; row <= mask_sub.y2; row += ds_num) {
/*Get and use the pointer of const data in program memory*/
if(const_data != false) {
uint8_t * f_data = ((ufs_file_t*)file.file_d)->ent->data_d;
f_data += ((ufs_file_t*)file.file_d)->rwp;
((ufs_file_t*)file.file_d)->rwp += useful_data;
map_fp(&act_area, &mask_sub, (void*)f_data , style->opa, header.transp, upscale,
style->ccolor, style->img_recolor);
}
/*Or read the NOT const files normally*/
else {
color_t buf[LV_HOR_RES];
res = fs_read(&file, buf, useful_data, &br);
map_fp(&act_area, &mask_sub, buf, style->opa, header.transp, upscale,
style->ccolor, style->img_recolor);
/*Read the img. with the FS interface*/
else {
uint8_t us_shift = 0;
uint8_t us_val = 1;
if(upscale != false) {
us_shift = 1;
us_val = 2;
}
fs_tell(&file, &act_pos);
fs_seek(&file, act_pos + next_row);
act_area.y1 += ds_num;
act_area.y2 += ds_num;
}
/* Move the file pointer to the start address according to mask
* But take care, the upscaled maps look greater*/
uint32_t start_offset = sizeof(lv_img_raw_header_t);
start_offset += (area_get_width(cords_p) >> us_shift) *
((mask_com.y1 - cords_p->y1) >> us_shift) * sizeof(color_t); /*First row*/
start_offset += ((mask_com.x1 - cords_p->x1) >> us_shift) * sizeof(color_t); /*First col*/
fs_seek(&file, start_offset);
uint32_t useful_data = (area_get_width(&mask_com) >> us_shift) * sizeof(color_t);
uint32_t next_row = (area_get_width(cords_p) >> us_shift) * sizeof(color_t) - useful_data;
area_t line;
area_cpy(&line, &mask_com);
area_set_height(&line, us_val); /*Create a line area. Hold 2 pixels if upscaled*/
cord_t row;
uint32_t act_pos;
color_t buf[LV_HOR_RES];
for(row = mask_com.y1; row <= mask_com.y2; row += us_val) {
res = fs_read(&file, buf, useful_data, &br);
map_fp(&line, &mask_com, buf, style->opa, header.transp, upscale,
style->ccolor, style->img_recolor);
fs_tell(&file, &act_pos);
fs_seek(&file, act_pos + next_row);
line.y1 += us_val; /*Go down a line*/
line.y2 += us_val;
}
}
}
fs_close(&file);
if(res != FS_RES_OK) {

View File

@ -31,6 +31,8 @@
/**********************
* STATIC PROTOTYPES
**********************/
static void sw_render_fill(area_t * mem_area, color_t * mem, const area_t * fill_area, color_t color, opa_t opa);
static inline void sw_render_map_line(color_t * mem, const color_t * map, cord_t map_len, opa_t opa);
/**********************
* STATIC VARIABLES
@ -99,55 +101,20 @@ void lv_vfill(const area_t * cords_p, const area_t * mask_p,
union_ok = area_union(&res_a, cords_p, mask_p);
/*If there are common part of the three area then draw to the vdb*/
if(union_ok == true) {
area_t vdb_rel_a; /*Stores relative coordinates on vdb*/
vdb_rel_a.x1 = res_a.x1 - vdb_p->area.x1;
vdb_rel_a.y1 = res_a.y1 - vdb_p->area.y1;
vdb_rel_a.x2 = res_a.x2 - vdb_p->area.x1;
vdb_rel_a.y2 = res_a.y2 - vdb_p->area.y1;
color_t * vdb_buf_tmp = vdb_p->buf;
uint32_t vdb_width = area_get_width(&vdb_p->area);
/*Move the vdb_tmp to the first row*/
vdb_buf_tmp += vdb_width * vdb_rel_a.y1;
/*Set all row in vdb to the given color*/
cord_t row;
uint32_t col;
/*Run simpler function without opacity*/
if(opa == OPA_COVER) {
/*Fill the first row with 'color'*/
for(col = vdb_rel_a.x1; col <= vdb_rel_a.x2; col++) {
vdb_buf_tmp[col] = color;
}
/*Copy the first row to all other rows*/
color_t * vdb_buf_first = &vdb_buf_tmp[vdb_rel_a.x1];
cord_t copy_size = (vdb_rel_a.x2 - vdb_rel_a.x1 + 1) * sizeof(color_t);
vdb_buf_tmp += vdb_width;
for(row = vdb_rel_a.y1 + 1; row <= vdb_rel_a.y2; row++) {
memcpy(&vdb_buf_tmp[vdb_rel_a.x1], vdb_buf_first, copy_size);
vdb_buf_tmp += vdb_width;
}
}
/*Calculate with alpha too*/
else {
color_t bg_tmp = COLOR_BLACK;
color_t opa_tmp = color_mix(color, bg_tmp, opa);
for(row = vdb_rel_a.y1; row <= vdb_rel_a.y2; row++) {
for(col = vdb_rel_a.x1; col <= vdb_rel_a.x2; col++) {
/*If the bg color changed recalculate the result color*/
if(vdb_buf_tmp[col].full != bg_tmp.full) {
bg_tmp = vdb_buf_tmp[col];
opa_tmp = color_mix(color, bg_tmp, opa);
}
vdb_buf_tmp[col] = opa_tmp;
}
vdb_buf_tmp += vdb_width;
}
}
}
if(union_ok == false) return;
area_t vdb_rel_a; /*Stores relative coordinates on vdb*/
vdb_rel_a.x1 = res_a.x1 - vdb_p->area.x1;
vdb_rel_a.y1 = res_a.y1 - vdb_p->area.y1;
vdb_rel_a.x2 = res_a.x2 - vdb_p->area.x1;
vdb_rel_a.y2 = res_a.y2 - vdb_p->area.y1;
color_t * vdb_buf_tmp = vdb_p->buf;
uint32_t vdb_width = area_get_width(&vdb_p->area);
/*Move the vdb_tmp to the first row*/
vdb_buf_tmp += vdb_width * vdb_rel_a.y1;
sw_render_fill(&vdb_p->area, vdb_buf_tmp, &vdb_rel_a, color, opa);
}
/**
@ -322,38 +289,22 @@ void lv_vmap(const area_t * cords_p, const area_t * mask_p,
color_t * vdb_buf_tmp = vdb_p->buf;
vdb_buf_tmp += (uint32_t) vdb_width * masked_a.y1; /*Move to the first row*/
map_p -= (masked_a.x1 >> ds_shift);
map_p -= (masked_a.x1 >> ds_shift); /*Move back. It will be easier to index 'map_p' later*/
/*No upscalse*/
if(upscale == false) {
if(transp == false) { /*Simply copy the pixels to the VDB*/
cord_t row;
if(opa == OPA_COVER) { /*no opa */
for(row = masked_a.y1; row <= masked_a.y2; row++) {
memcpy(&vdb_buf_tmp[masked_a.x1],
&map_p[masked_a.x1],
area_get_width(&masked_a) * sizeof(color_t));
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
} else { /*with opacity*/
cord_t col;
for(row = masked_a.y1; row <= masked_a.y2; row++) {
for(col = masked_a.x1; col <= masked_a.x2; col ++) {
vdb_buf_tmp[col] = color_mix( map_p[col], vdb_buf_tmp[col], opa);
}
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
for(row = masked_a.y1; row <= masked_a.y2; row++) {
sw_render_map_line(&vdb_buf_tmp[masked_a.x1], &map_p[masked_a.x1], map_width, opa);
map_p += map_width; /*Next row on the map*/
vdb_buf_tmp += vdb_width; /*Next row on the VDB*/
}
#if LV_VDB_SIZE != 0
/*To recolor draw simply a rectangle above the image*/
if(recolor_opa != OPA_TRANSP) {
lv_vfill(cords_p, mask_p, recolor, recolor_opa);
}
#endif
} else { /*transp == true: Check all pixels */
cord_t row;
cord_t col;
@ -473,10 +424,76 @@ void lv_vmap(const area_t * cords_p, const area_t * mask_p,
}
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
*
* @param mem_area coordinates of 'mem' memory area
* @param mem a memory address. Considered to a rectangual window according to 'mem_area'
* @param fill_area coordinates of an area to fill. Relative to 'mem_area'.
* @param color fill color
* @param opa opacity (0, OPA_TRANSP: transparent ... 255, OPA_COVER, fully cover)
*/
static void sw_render_fill(area_t * mem_area, color_t * mem, const area_t * fill_area, color_t color, opa_t opa)
{
/*Set all row in vdb to the given color*/
cord_t row;
uint32_t col;
cord_t mem_width = area_get_width(mem_area);
/*Run simpler function without opacity*/
if(opa == OPA_COVER) {
/*Fill the first row with 'color'*/
for(col = fill_area->x1; col <= fill_area->x2; col++) {
mem[col] = color;
}
/*Copy the first row to all other rows*/
color_t * mem_first = &mem[fill_area->x1];
cord_t copy_size = (fill_area->x2 - fill_area->x1 + 1) * sizeof(color_t);
mem += mem_width;
for(row = fill_area->y1 + 1; row <= fill_area->y2; row++) {
memcpy(&mem[fill_area->x1], mem_first, copy_size);
mem += mem_width;
}
}
/*Calculate with alpha too*/
else {
color_t bg_tmp = COLOR_BLACK;
color_t opa_tmp = color_mix(color, bg_tmp, opa);
for(row = fill_area->y1; row <= fill_area->y2; row++) {
for(col = fill_area->x1; col <= fill_area->x2; col++) {
/*If the bg color changed recalculate the result color*/
if(mem[col].full != bg_tmp.full) {
bg_tmp = mem[col];
opa_tmp = color_mix(color, bg_tmp, opa);
}
mem[col] = opa_tmp;
}
mem += mem_width;
}
}
}
/**
* Copy one line of pixel map into a memory using opacity
* @param mem a memory address. Copy 'map' here.
* @param map pointer to pixel map. Copy it to 'mem'.
* @param map_len number of pixels in 'map'
* @param opa opacity (0, OPA_TRANSP: transparent ... 255, OPA_COVER, fully cover)
*/
static inline void sw_render_map_line(color_t * mem, const color_t * map, cord_t map_len, opa_t opa)
{
if(opa == OPA_COVER) { /*no opa */
memcpy(mem, map, map_len * sizeof(color_t));
} else { /*with opacity*/
cord_t x;
for(x = 0; x <= map_len; x ++) {
mem[x] = color_mix(map[x], mem[x], opa);
}
}
}
#endif