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