1 /**
2 * @file lv_draw_dave2d.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_draw_dave2d.h"
10 #if LV_USE_DRAW_DAVE2D
11 #include "../../lv_draw_buf_private.h"
12 #include "../../../misc/lv_area_private.h"
13
14 /*********************
15 * DEFINES
16 *********************/
17 #define DRAW_UNIT_ID_DAVE2D 4
18
19 /**********************
20 * TYPEDEFS
21 **********************/
22
23 /**********************
24 * STATIC PROTOTYPES
25 **********************/
26 #if LV_USE_OS
27 static void _dave2d_render_thread_cb(void * ptr);
28 #endif
29
30 static void execute_drawing(lv_draw_dave2d_unit_t * u);
31
32 #if defined(RENESAS_CORTEX_M85)
33 #if (BSP_CFG_DCACHE_ENABLED)
34 static void _dave2d_buf_invalidate_cache_cb(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
35 #endif
36 #endif
37
38 static int32_t _dave2d_evaluate(lv_draw_unit_t * draw_unit, lv_draw_task_t * task);
39
40 static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer);
41
42 static d2_s32 lv_dave2d_init(void);
43
44 static void lv_draw_buf_dave2d_init_handlers(void);
45
46 void dave2d_execute_dlist_and_flush(void);
47
48 /**********************
49 * GLOBAL PROTOTYPES
50 **********************/
51
52 /**********************
53 * STATIC VARIABLES
54 **********************/
55
56 d2_device * _d2_handle;
57 d2_renderbuffer * _renderbuffer;
58 d2_renderbuffer * _blit_renderbuffer;
59
60 lv_ll_t _ll_Dave2D_Tasks;
61
62 #if LV_USE_OS
63 lv_mutex_t xd2Semaphore;
64 #endif
65
66 /**********************
67 * MACROS
68 **********************/
69
70 /**********************
71 * GLOBAL FUNCTIONS
72 **********************/
73
lv_draw_dave2d_init(void)74 void lv_draw_dave2d_init(void)
75 {
76 d2_s32 result = D2_OK;
77
78 lv_draw_buf_dave2d_init_handlers();
79
80 lv_draw_dave2d_unit_t * draw_dave2d_unit = lv_draw_create_unit(sizeof(lv_draw_dave2d_unit_t));
81 draw_dave2d_unit->base_unit.dispatch_cb = lv_draw_dave2d_dispatch;
82 draw_dave2d_unit->base_unit.evaluate_cb = _dave2d_evaluate;
83 draw_dave2d_unit->base_unit.name = "DAVE2D";
84 draw_dave2d_unit->idx = DRAW_UNIT_ID_DAVE2D;
85
86 result = lv_dave2d_init();
87 LV_ASSERT(D2_OK == result);
88
89 #if LV_USE_OS
90 lv_result_t res;
91 res = lv_mutex_init(&xd2Semaphore);
92 LV_ASSERT(LV_RESULT_OK == res);
93
94 draw_dave2d_unit->pd2Mutex = &xd2Semaphore;
95 #endif
96
97 draw_dave2d_unit->d2_handle = _d2_handle;
98 draw_dave2d_unit->renderbuffer = _renderbuffer;
99 lv_ll_init(&_ll_Dave2D_Tasks, 4);
100
101 #if LV_USE_OS
102 lv_thread_init(&draw_dave2d_unit->thread, "dave2d", LV_THREAD_PRIO_HIGH, _dave2d_render_thread_cb, 8 * 1024,
103 draw_dave2d_unit);
104 #endif
105
106 }
107
108 /**********************
109 * STATIC FUNCTIONS
110 **********************/
111
lv_draw_buf_dave2d_init_handlers(void)112 static void lv_draw_buf_dave2d_init_handlers(void)
113 {
114
115 #if defined(RENESAS_CORTEX_M85)
116 #if (BSP_CFG_DCACHE_ENABLED)
117 lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers();
118 handlers->invalidate_cache_cb = _dave2d_buf_invalidate_cache_cb;
119 #endif
120 #endif
121 }
122
123 #if defined(RENESAS_CORTEX_M85)
124 #if (BSP_CFG_DCACHE_ENABLED)
_dave2d_buf_invalidate_cache_cb(const lv_draw_buf_t * draw_buf,const lv_area_t * area)125 static void _dave2d_buf_invalidate_cache_cb(const lv_draw_buf_t * draw_buf, const lv_area_t * area)
126 {
127 const lv_image_header_t * header = &draw_buf->header;
128 uint32_t stride = header->stride;
129 lv_color_format_t cf = header->cf;
130
131 uint8_t * address = draw_buf->data;
132 int32_t i = 0;
133 uint32_t bytes_per_pixel = lv_color_format_get_size(cf);
134 int32_t width = lv_area_get_width(area);
135 int32_t lines = lv_area_get_height(area);
136 int32_t bytes_to_flush_per_line = (int32_t)width * (int32_t)bytes_per_pixel;
137
138 /* Stride is in bytes, not pixels */
139 address = address + (area->x1 * (int32_t)bytes_per_pixel) + (stride * (uint32_t)area->y1);
140
141 for(i = 0; i < lines; i++) {
142 SCB_CleanInvalidateDCache_by_Addr(address, bytes_to_flush_per_line);
143 address += stride;
144 }
145 }
146 #endif
147 #endif
148
149 /**
150 * @todo
151 * LVGL needs to use hardware acceleration for buf_copy and do not affect GPU rendering.
152 */
153 #if 0
154 static void _dave2d_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area,
155 void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area, lv_color_format_t color_format)
156 {
157 d2_s32 result;
158
159 #if LV_USE_OS
160 lv_result_t status;
161
162 status = lv_mutex_lock(&xd2Semaphore);
163 LV_ASSERT(LV_RESULT_OK == status);
164 #endif
165
166 d2_u32 src_blend_mode = d2_getblendmodesrc(_d2_handle);
167 d2_u32 dst_blend_mode = d2_getblendmodedst(_d2_handle);
168
169 result = d2_selectrenderbuffer(_d2_handle, _blit_renderbuffer);
170 LV_ASSERT(D2_OK == result);
171
172 result = d2_setblendmode(_d2_handle, d2_bm_one, d2_bm_zero);
173 LV_ASSERT(D2_OK == result);
174
175 // Generate render operations
176 result = d2_framebuffer(_d2_handle, (uint16_t *)dest_buf, DISPLAY_HSIZE_INPUT0, DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0,
177 DISPLAY_VSIZE_INPUT0, lv_draw_dave2d_cf_fb_get());
178 LV_ASSERT(D2_OK == result);
179
180 result = d2_cliprect(_d2_handle, (d2_border)dest_area->x1, (d2_border)dest_area->y1, (d2_border)dest_area->x2,
181 (d2_border)dest_area->y2);
182 LV_ASSERT(D2_OK == result);
183
184 result = d2_setblitsrc(_d2_handle, (void *) src_buf, (d2_s32)src_w, (d2_s32)src_w, (d2_s32)src_h,
185 lv_draw_dave2d_lv_colour_fmt_to_d2_fmt(color_format));
186 LV_ASSERT(D2_OK == result);
187
188 result = d2_blitcopy(_d2_handle, (d2_s32)src_w, (d2_s32)src_h, (d2_blitpos)src_area->x1, (d2_blitpos)src_area->y1,
189 D2_FIX4(dest_w), D2_FIX4(dest_h),
190 D2_FIX4(dest_area->x1), D2_FIX4(dest_area->y1), 0);
191 LV_ASSERT(D2_OK == result);
192
193 // Execute render operations
194 result = d2_executerenderbuffer(_d2_handle, _blit_renderbuffer, 0);
195 LV_ASSERT(D2_OK == result) ;
196
197 result = d2_flushframe(_d2_handle);
198 LV_ASSERT(D2_OK == result);
199
200 result = d2_selectrenderbuffer(_d2_handle, _renderbuffer);
201 LV_ASSERT(D2_OK == result);
202
203 result = d2_setblendmode(_d2_handle, src_blend_mode, dst_blend_mode);
204 LV_ASSERT(D2_OK != result);
205
206 #if LV_USE_OS
207 status = lv_mutex_unlock(&xd2Semaphore);
208 LV_ASSERT(LV_RESULT_OK == status);
209 #endif
210
211 }
212 #endif
213
214 #define USE_D2 (1)
215
_dave2d_evaluate(lv_draw_unit_t * u,lv_draw_task_t * t)216 static int32_t _dave2d_evaluate(lv_draw_unit_t * u, lv_draw_task_t * t)
217 {
218 LV_UNUSED(u);
219 int32_t ret = 0;
220
221 lv_draw_dsc_base_t * draw_dsc_base = (lv_draw_dsc_base_t *) t->draw_dsc;
222
223 if(!lv_draw_dave2d_is_dest_cf_supported(draw_dsc_base->layer->color_format))
224 return 0;
225
226 switch(t->type) {
227 case LV_DRAW_TASK_TYPE_FILL: {
228 #if USE_D2
229 lv_draw_fill_dsc_t * dsc = t->draw_dsc;
230 if(dsc->grad.dir == LV_GRAD_DIR_NONE
231 || ((dsc->grad.dir != LV_GRAD_DIR_NONE)
232 && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue)
233 && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red)
234 && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) {
235
236 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
237 t->preference_score = 0;
238
239 }
240 else
241 #endif
242 {
243 }
244 ret = 0;
245 break;
246 }
247 case LV_DRAW_TASK_TYPE_LAYER: {
248 ret = 0;
249 break;
250 }
251
252 case LV_DRAW_TASK_TYPE_IMAGE: {
253 lv_draw_image_dsc_t * dsc = t->draw_dsc;
254 if((dsc->header.cf >= LV_COLOR_FORMAT_PROPRIETARY_START) || (dsc->header.cf == LV_COLOR_FORMAT_RGB888)) {
255 ret = 0;
256 break;
257 }
258 #if USE_D2
259 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
260 t->preference_score = 0;
261 #endif
262 ret = 0;
263 break;
264 }
265
266 case LV_DRAW_TASK_TYPE_BORDER: {
267 #if USE_D2
268 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
269 t->preference_score = 0;
270 #endif
271 ret = 0;
272 break;
273 }
274
275 case LV_DRAW_TASK_TYPE_BOX_SHADOW: {
276 ret = 0;
277 break;
278 }
279
280 case LV_DRAW_TASK_TYPE_LABEL: {
281 #if USE_D2
282 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
283 t->preference_score = 0;
284 #endif
285 ret = 0;
286 break;
287 }
288
289 case LV_DRAW_TASK_TYPE_LINE: {
290 #if USE_D2
291 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
292 t->preference_score = 0;
293 #endif
294 ret = 0;
295 break;
296 }
297
298 case LV_DRAW_TASK_TYPE_ARC: {
299 #if USE_D2
300 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
301 t->preference_score = 0;
302 #endif
303 ret = 0;
304 break;
305 }
306
307 case LV_DRAW_TASK_TYPE_TRIANGLE: {
308 #if USE_D2
309 lv_draw_fill_dsc_t * dsc = t->draw_dsc;
310 if(dsc->grad.dir == LV_GRAD_DIR_NONE
311 || ((dsc->grad.dir != LV_GRAD_DIR_NONE)
312 && ((dsc->grad.stops[0].color.blue == dsc->grad.stops[dsc->grad.stops_count - 1].color.blue)
313 && (dsc->grad.stops[0].color.red == dsc->grad.stops[dsc->grad.stops_count - 1].color.red)
314 && (dsc->grad.stops[0].color.green == dsc->grad.stops[dsc->grad.stops_count - 1].color.green)))) {
315 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
316 t->preference_score = 0;
317 }
318 else {
319 }
320 #endif
321 ret = 0;
322 break;
323 }
324
325 case LV_DRAW_TASK_TYPE_MASK_RECTANGLE: {
326 #if 0//USE_D2
327 t->preferred_draw_unit_id = DRAW_UNIT_ID_DAVE2D;
328 t->preference_score = 0;
329 #endif
330 ret = 0;
331 break;
332 }
333
334 case LV_DRAW_TASK_TYPE_MASK_BITMAP: {
335 ret = 0;
336 break;
337 }
338
339 default:
340 ret = 0;
341 break;
342 }
343
344 return ret;
345 }
346
347 #define DAVE2D_REFERRING_WATERMARK 10
348
lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit,lv_layer_t * layer)349 static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
350 {
351 lv_draw_dave2d_unit_t * draw_dave2d_unit = (lv_draw_dave2d_unit_t *) draw_unit;
352 #if (0 == D2_RENDER_EACH_OPERATION)
353 static uint32_t ref_count = 0;
354 #endif
355
356 /*Return immediately if it's busy with draw task*/
357 if(draw_dave2d_unit->task_act) return 0;
358
359 lv_draw_task_t * t = NULL;
360 t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
361 while(t && t->preferred_draw_unit_id != DRAW_UNIT_ID_DAVE2D) {
362 t->state = LV_DRAW_TASK_STATE_READY;
363 t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
364 }
365
366 if(t == NULL) {
367 #if (0 == D2_RENDER_EACH_OPERATION)
368 if(false == lv_ll_is_empty(&_ll_Dave2D_Tasks)) {
369 ref_count = 0;
370 dave2d_execute_dlist_and_flush();
371 }
372 #endif
373 return LV_DRAW_UNIT_IDLE; /*Couldn't start rendering*/
374 }
375
376 /* Return if target buffer format is not supported. */
377 if(!lv_draw_dave2d_is_dest_cf_supported(layer->color_format)) {
378 return LV_DRAW_UNIT_IDLE; /*Couldn't start rendering*/
379 }
380
381 void * buf = lv_draw_layer_alloc_buf(layer);
382 if(buf == NULL) {
383 return LV_DRAW_UNIT_IDLE; /*Couldn't start rendering*/
384 }
385
386 #if (0 == D2_RENDER_EACH_OPERATION)
387 ref_count += lv_draw_get_dependent_count(t);
388
389 if(DAVE2D_REFERRING_WATERMARK < ref_count) {
390 ref_count = 0;
391 dave2d_execute_dlist_and_flush();
392 }
393
394 lv_draw_task_t ** p_new_list_entry;
395 p_new_list_entry = lv_ll_ins_tail(&_ll_Dave2D_Tasks);
396 *p_new_list_entry = t;
397 #endif
398
399 t->state = LV_DRAW_TASK_STATE_IN_PROGRESS;
400 draw_dave2d_unit->base_unit.target_layer = layer;
401 draw_dave2d_unit->base_unit.clip_area = &t->clip_area;
402 draw_dave2d_unit->task_act = t;
403
404 #if LV_USE_OS
405 /*Let the render thread work*/
406 lv_thread_sync_signal(&draw_dave2d_unit->sync);
407 #else
408 execute_drawing(draw_dave2d_unit);
409 #if (D2_RENDER_EACH_OPERATION)
410 draw_dave2d_unit->task_act->state = LV_DRAW_TASK_STATE_READY;
411 #endif
412 draw_dave2d_unit->task_act = NULL;
413
414 /*The draw unit is free now. Request a new dispatching as it can get a new task*/
415 lv_draw_dispatch_request();
416
417 #endif
418 return 1;
419 }
420
421 #if LV_USE_OS
_dave2d_render_thread_cb(void * ptr)422 static void _dave2d_render_thread_cb(void * ptr)
423 {
424 lv_draw_dave2d_unit_t * u = ptr;
425
426 lv_thread_sync_init(&u->sync);
427
428 while(1) {
429 while(u->task_act == NULL) {
430 lv_thread_sync_wait(&u->sync);
431 }
432
433 execute_drawing(u);
434
435 /*Cleanup*/
436 #if (D2_RENDER_EACH_OPERATION)
437 u->task_act->state = LV_DRAW_TASK_STATE_READY;
438 #endif
439 u->task_act = NULL;
440
441 /*The draw unit is free now. Request a new dispatching as it can get a new task*/
442 lv_draw_dispatch_request();
443 }
444 }
445 #endif
446
execute_drawing(lv_draw_dave2d_unit_t * u)447 static void execute_drawing(lv_draw_dave2d_unit_t * u)
448 {
449 /*Render the draw task*/
450 lv_draw_task_t * t = u->task_act;
451
452 #if defined(RENESAS_CORTEX_M85)
453 #if (BSP_CFG_DCACHE_ENABLED)
454 lv_layer_t * layer = u->base_unit.target_layer;
455 lv_area_t clipped_area;
456 int32_t x;
457 int32_t y;
458
459 lv_area_intersect(&clipped_area, &t->area, u->base_unit.clip_area);
460
461 x = 0 - u->base_unit.target_layer->buf_area.x1;
462 y = 0 - u->base_unit.target_layer->buf_area.y1;
463
464 lv_area_move(&clipped_area, x, y);
465
466 /* Invalidate cache */
467 lv_draw_buf_invalidate_cache(layer->draw_buf, &clipped_area);
468 #endif
469 #endif
470
471 switch(t->type) {
472 case LV_DRAW_TASK_TYPE_FILL:
473 lv_draw_dave2d_fill(u, t->draw_dsc, &t->area);
474 break;
475 case LV_DRAW_TASK_TYPE_BORDER:
476 lv_draw_dave2d_border(u, t->draw_dsc, &t->area);
477 break;
478 case LV_DRAW_TASK_TYPE_BOX_SHADOW:
479 //lv_draw_dave2d_box_shadow(u, t->draw_dsc, &t->area);
480 break;
481 #if 0
482 case LV_DRAW_TASK_TYPE_BG_IMG:
483 //lv_draw_dave2d_bg_image(u, t->draw_dsc, &t->area);
484 break;
485 #endif
486 case LV_DRAW_TASK_TYPE_LABEL:
487 lv_draw_dave2d_label(u, t->draw_dsc, &t->area);
488 break;
489 case LV_DRAW_TASK_TYPE_IMAGE:
490 lv_draw_dave2d_image(u, t->draw_dsc, &t->area);
491 break;
492 case LV_DRAW_TASK_TYPE_LINE:
493 lv_draw_dave2d_line(u, t->draw_dsc);
494 break;
495 case LV_DRAW_TASK_TYPE_ARC:
496 lv_draw_dave2d_arc(u, t->draw_dsc, &t->area);
497 break;
498 case LV_DRAW_TASK_TYPE_TRIANGLE:
499 lv_draw_dave2d_triangle(u, t->draw_dsc);
500 break;
501 case LV_DRAW_TASK_TYPE_LAYER:
502 //lv_draw_dave2d_layer(u, t->draw_dsc, &t->area);
503 break;
504 case LV_DRAW_TASK_TYPE_MASK_RECTANGLE:
505 //lv_draw_dave2d_mask_rect(u, t->draw_dsc, &t->area);
506 break;
507 default:
508 break;
509 }
510
511 }
512
lv_dave2d_init(void)513 static d2_s32 lv_dave2d_init(void)
514 {
515 d2_s32 result = D2_OK;
516
517 if(_d2_handle != NULL) {
518 return D2_NOMEMORY;
519 }
520
521 _d2_handle = d2_opendevice(0);
522 if(_d2_handle == NULL) {
523 return D2_NOMEMORY;
524 }
525
526 /* bind the hardware */
527 result = d2_inithw(_d2_handle, 0);
528 if(result != D2_OK) {
529 LV_LOG_ERROR("Could NOT d2_inithw");
530 d2_closedevice(_d2_handle);
531 return result;
532 }
533
534 //
535 // Set various D2 parameters
536 //
537 result = d2_setblendmode(_d2_handle, d2_bm_alpha, d2_bm_one_minus_alpha);
538 result = d2_setalphamode(_d2_handle, d2_am_constant);
539 result = d2_setalpha(_d2_handle, UINT8_MAX);
540 result = d2_setantialiasing(_d2_handle, 1);
541 result = d2_setlinecap(_d2_handle, d2_lc_butt);
542 result = d2_setlinejoin(_d2_handle, d2_lj_miter);
543
544 /* set blocksize for default displaylist */
545 result = d2_setdlistblocksize(_d2_handle, 25);
546 if(D2_OK != result) {
547 LV_LOG_ERROR("Could NOT d2_setdlistblocksize");
548 d2_closedevice(_d2_handle);
549 return result;
550 }
551
552 _blit_renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20);
553 if(!_blit_renderbuffer) {
554 LV_LOG_ERROR("NO renderbuffer");
555 d2_closedevice(_d2_handle);
556
557 return D2_NOMEMORY;
558 }
559
560 _renderbuffer = d2_newrenderbuffer(_d2_handle, 20, 20);
561 if(!_renderbuffer) {
562 LV_LOG_ERROR("NO renderbuffer");
563 d2_closedevice(_d2_handle);
564
565 return D2_NOMEMORY;
566 }
567
568 result = d2_selectrenderbuffer(_d2_handle, _renderbuffer);
569 if(D2_OK != result) {
570 LV_LOG_ERROR("Could NOT d2_selectrenderbuffer");
571 d2_closedevice(_d2_handle);
572 }
573
574 return result;
575 }
576
dave2d_execute_dlist_and_flush(void)577 void dave2d_execute_dlist_and_flush(void)
578 {
579 #if LV_USE_OS
580 lv_result_t status;
581
582 status = lv_mutex_lock(&xd2Semaphore);
583 LV_ASSERT(LV_RESULT_OK == status);
584 #endif
585
586 d2_s32 result;
587 lv_draw_task_t ** p_list_entry;
588 lv_draw_task_t * p_list_entry1;
589
590 // Execute render operations
591 result = d2_executerenderbuffer(_d2_handle, _renderbuffer, 0);
592 LV_ASSERT(D2_OK == result);
593
594 result = d2_flushframe(_d2_handle);
595 LV_ASSERT(D2_OK == result);
596
597 result = d2_selectrenderbuffer(_d2_handle, _renderbuffer);
598 LV_ASSERT(D2_OK == result);
599
600 while(false == lv_ll_is_empty(&_ll_Dave2D_Tasks)) {
601 p_list_entry = lv_ll_get_tail(&_ll_Dave2D_Tasks);
602 p_list_entry1 = *p_list_entry;
603 p_list_entry1->state = LV_DRAW_TASK_STATE_READY;
604 lv_ll_remove(&_ll_Dave2D_Tasks, p_list_entry);
605 lv_free(p_list_entry);
606 }
607
608 #if LV_USE_OS
609 status = lv_mutex_unlock(&xd2Semaphore);
610 LV_ASSERT(LV_RESULT_OK == status);
611 #endif
612 }
613
614 #endif /*LV_USE_DRAW_DAVE2D*/
615