1 /**
2  * @file lv_vg_lite_draw.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 
10 #include "lv_draw_vg_lite.h"
11 
12 #if LV_USE_DRAW_VG_LITE
13 
14 #include "../lv_draw_private.h"
15 #include "lv_draw_vg_lite_type.h"
16 #include "lv_vg_lite_path.h"
17 #include "lv_vg_lite_utils.h"
18 #include "lv_vg_lite_decoder.h"
19 #include "lv_vg_lite_grad.h"
20 #include "lv_vg_lite_pending.h"
21 #include "lv_vg_lite_stroke.h"
22 
23 /*********************
24  *      DEFINES
25  *********************/
26 
27 #define VG_LITE_DRAW_UNIT_ID 2
28 
29 /**********************
30  *      TYPEDEFS
31  **********************/
32 
33 /**********************
34  *  STATIC PROTOTYPES
35  **********************/
36 
37 static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
38 
39 static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
40 
41 static int32_t draw_delete(lv_draw_unit_t * draw_unit);
42 
43 /**********************
44  *  STATIC VARIABLES
45  **********************/
46 
47 /**********************
48  *      MACROS
49  **********************/
50 
51 /**********************
52  *   GLOBAL FUNCTIONS
53  **********************/
54 
lv_draw_vg_lite_init(void)55 void lv_draw_vg_lite_init(void)
56 {
57 #if LV_VG_LITE_USE_GPU_INIT
58     extern void gpu_init(void);
59     static bool inited = false;
60     if(!inited) {
61         gpu_init();
62         inited = true;
63     }
64 #endif
65 
66     lv_vg_lite_dump_info();
67 
68     lv_draw_buf_vg_lite_init_handlers();
69 
70     lv_draw_vg_lite_unit_t * unit = lv_draw_create_unit(sizeof(lv_draw_vg_lite_unit_t));
71     unit->base_unit.dispatch_cb = draw_dispatch;
72     unit->base_unit.evaluate_cb = draw_evaluate;
73     unit->base_unit.delete_cb = draw_delete;
74     unit->base_unit.name = "VG_LITE";
75 
76     lv_vg_lite_image_dsc_init(unit);
77 #if LV_USE_VECTOR_GRAPHIC
78     lv_vg_lite_grad_init(unit, LV_VG_LITE_GRAD_CACHE_CNT);
79     lv_vg_lite_stroke_init(unit, LV_VG_LITE_STROKE_CACHE_CNT);
80 #endif
81     lv_vg_lite_path_init(unit);
82     lv_vg_lite_decoder_init();
83     lv_draw_vg_lite_label_init(&unit->base_unit);
84 }
85 
lv_draw_vg_lite_deinit(void)86 void lv_draw_vg_lite_deinit(void)
87 {
88 }
89 
90 /**********************
91  *   STATIC FUNCTIONS
92  **********************/
93 
check_image_is_supported(const lv_draw_image_dsc_t * dsc)94 static bool check_image_is_supported(const lv_draw_image_dsc_t * dsc)
95 {
96     return lv_vg_lite_is_src_cf_supported(dsc->header.cf);
97 }
98 
check_arc_is_supported(const lv_draw_arc_dsc_t * dsc)99 static bool check_arc_is_supported(const lv_draw_arc_dsc_t * dsc)
100 {
101     if(dsc->img_src == NULL) {
102         return true;
103     }
104 
105     lv_image_header_t header;
106     lv_result_t res = lv_image_decoder_get_info(dsc->img_src, &header);
107     if(res != LV_RESULT_OK) {
108         LV_LOG_TRACE("get image info failed");
109         return false;
110     }
111 
112     return lv_vg_lite_is_src_cf_supported(header.cf);
113 }
114 
draw_execute(lv_draw_vg_lite_unit_t * u)115 static void draw_execute(lv_draw_vg_lite_unit_t * u)
116 {
117     lv_draw_task_t * t = u->task_act;
118     lv_draw_unit_t * draw_unit = (lv_draw_unit_t *)u;
119 
120     lv_layer_t * layer = u->base_unit.target_layer;
121 
122     lv_vg_lite_buffer_from_draw_buf(&u->target_buffer, layer->draw_buf);
123 
124     /* VG-Lite will output premultiplied image, set the flag correspondingly. */
125     lv_draw_buf_set_flag(layer->draw_buf, LV_IMAGE_FLAGS_PREMULTIPLIED);
126 
127     vg_lite_identity(&u->global_matrix);
128     if(layer->buf_area.x1 || layer->buf_area.y1) {
129         vg_lite_translate(-layer->buf_area.x1, -layer->buf_area.y1, &u->global_matrix);
130     }
131 
132 #if LV_DRAW_TRANSFORM_USE_MATRIX
133     vg_lite_matrix_t layer_matrix;
134     lv_vg_lite_matrix(&layer_matrix, &t->matrix);
135     lv_vg_lite_matrix_multiply(&u->global_matrix, &layer_matrix);
136 
137     /* Crop out extra pixels drawn due to scaling accuracy issues */
138     if(vg_lite_query_feature(gcFEATURE_BIT_VG_SCISSOR)) {
139         lv_area_t scissor_area = layer->phy_clip_area;
140         lv_area_move(&scissor_area, -layer->buf_area.x1, -layer->buf_area.y1);
141         lv_vg_lite_set_scissor_area(&scissor_area);
142     }
143 #endif
144 
145     switch(t->type) {
146         case LV_DRAW_TASK_TYPE_LETTER:
147             lv_draw_vg_lite_letter(draw_unit, t->draw_dsc, &t->area);
148             break;
149         case LV_DRAW_TASK_TYPE_LABEL:
150             lv_draw_vg_lite_label(draw_unit, t->draw_dsc, &t->area);
151             break;
152         case LV_DRAW_TASK_TYPE_FILL:
153             lv_draw_vg_lite_fill(draw_unit, t->draw_dsc, &t->area);
154             break;
155         case LV_DRAW_TASK_TYPE_BORDER:
156             lv_draw_vg_lite_border(draw_unit, t->draw_dsc, &t->area);
157             break;
158         case LV_DRAW_TASK_TYPE_BOX_SHADOW:
159             lv_draw_vg_lite_box_shadow(draw_unit, t->draw_dsc, &t->area);
160             break;
161         case LV_DRAW_TASK_TYPE_IMAGE:
162             lv_draw_vg_lite_img(draw_unit, t->draw_dsc, &t->area, false);
163             break;
164         case LV_DRAW_TASK_TYPE_ARC:
165             lv_draw_vg_lite_arc(draw_unit, t->draw_dsc, &t->area);
166             break;
167         case LV_DRAW_TASK_TYPE_LINE:
168             lv_draw_vg_lite_line(draw_unit, t->draw_dsc);
169             break;
170         case LV_DRAW_TASK_TYPE_LAYER:
171             lv_draw_vg_lite_layer(draw_unit, t->draw_dsc, &t->area);
172             break;
173         case LV_DRAW_TASK_TYPE_TRIANGLE:
174             lv_draw_vg_lite_triangle(draw_unit, t->draw_dsc);
175             break;
176         case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
177             lv_draw_vg_lite_mask_rect(draw_unit, t->draw_dsc, &t->area);
178             break;
179 #if LV_USE_VECTOR_GRAPHIC
180         case LV_DRAW_TASK_TYPE_VECTOR:
181             lv_draw_vg_lite_vector(draw_unit, t->draw_dsc);
182             break;
183 #endif
184         default:
185             break;
186     }
187 
188     lv_vg_lite_flush(u);
189 }
190 
draw_dispatch(lv_draw_unit_t * draw_unit,lv_layer_t * layer)191 static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
192 {
193     lv_draw_vg_lite_unit_t * u = (lv_draw_vg_lite_unit_t *)draw_unit;
194 
195     /* Return immediately if it's busy with draw task. */
196     if(u->task_act) {
197         return 0;
198     }
199 
200     /* Try to get an ready to draw. */
201     lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID);
202 
203     /* Return 0 is no selection, some tasks can be supported by other units. */
204     if(!t || t->preferred_draw_unit_id != VG_LITE_DRAW_UNIT_ID) {
205         lv_vg_lite_finish(u);
206         return LV_DRAW_UNIT_IDLE;
207     }
208 
209     /* Return if target buffer format is not supported. */
210     if(!lv_vg_lite_is_dest_cf_supported(layer->color_format)) {
211         return LV_DRAW_UNIT_IDLE;
212     }
213 
214     void * buf = lv_draw_layer_alloc_buf(layer);
215     if(!buf) {
216         return LV_DRAW_UNIT_IDLE;
217     }
218 
219     t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
220     u->base_unit.target_layer = layer;
221     u->base_unit.clip_area = &t->clip_area;
222     u->task_act = t;
223 
224     draw_execute(u);
225 
226     u->task_act->state = LV_DRAW_TASK_STATE_READY;
227     u->task_act = NULL;
228 
229     /*The draw unit is free now. Request a new dispatching as it can get a new task*/
230     lv_draw_dispatch_request();
231 
232     return 1;
233 }
234 
draw_evaluate(lv_draw_unit_t * draw_unit,lv_draw_task_t * task)235 static int32_t draw_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task)
236 {
237     LV_UNUSED(draw_unit);
238 
239     /* Return if target buffer format is not supported. */
240     const lv_draw_dsc_base_t * base_dsc = task->draw_dsc;
241     if(!lv_vg_lite_is_dest_cf_supported(base_dsc->layer->color_format)) {
242         return -1;
243     }
244 
245     switch(task->type) {
246         case LV_DRAW_TASK_TYPE_LETTER:
247         case LV_DRAW_TASK_TYPE_LABEL:
248         case LV_DRAW_TASK_TYPE_FILL:
249         case LV_DRAW_TASK_TYPE_BORDER:
250 #if LV_VG_LITE_USE_BOX_SHADOW
251         case LV_DRAW_TASK_TYPE_BOX_SHADOW:
252 #endif
253         case LV_DRAW_TASK_TYPE_LAYER:
254         case LV_DRAW_TASK_TYPE_LINE:
255         case LV_DRAW_TASK_TYPE_TRIANGLE:
256         case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
257 
258 #if LV_USE_VECTOR_GRAPHIC
259         case LV_DRAW_TASK_TYPE_VECTOR:
260 #endif
261             break;
262 
263         case LV_DRAW_TASK_TYPE_ARC: {
264                 if(!check_arc_is_supported(task->draw_dsc)) {
265                     return 0;
266                 }
267             }
268             break;
269 
270         case LV_DRAW_TASK_TYPE_IMAGE: {
271                 if(!check_image_is_supported(task->draw_dsc)) {
272                     return 0;
273                 }
274             }
275             break;
276 
277         default:
278             /*The draw unit is not able to draw this task. */
279             return 0;
280     }
281 
282     /* The draw unit is able to draw this task. */
283     task->preference_score = 80;
284     task->preferred_draw_unit_id = VG_LITE_DRAW_UNIT_ID;
285     return 1;
286 }
287 
draw_delete(lv_draw_unit_t * draw_unit)288 static int32_t draw_delete(lv_draw_unit_t * draw_unit)
289 {
290     lv_draw_vg_lite_unit_t * unit = (lv_draw_vg_lite_unit_t *)draw_unit;
291 
292     lv_vg_lite_image_dsc_deinit(unit);
293 #if LV_USE_VECTOR_GRAPHIC
294     lv_vg_lite_grad_deinit(unit);
295     lv_vg_lite_stroke_deinit(unit);
296 #endif
297     lv_vg_lite_path_deinit(unit);
298     lv_vg_lite_decoder_deinit();
299     return 1;
300 }
301 
302 #endif /*LV_USE_DRAW_VG_LITE*/
303