diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index 02b2034bc6..8b22893442 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -147,17 +147,17 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t) void lv_draw_dispatch(void) { LV_PROFILER_BEGIN; - bool one_taken = false; + bool render_running = false; lv_display_t * disp = lv_display_get_next(NULL); while(disp) { lv_layer_t * layer = disp->layer_head; while(layer) { - bool ret = lv_draw_dispatch_layer(disp, layer); - if(ret) one_taken = true; + if(lv_draw_dispatch_layer(disp, layer)) + render_running = true; layer = layer->next; } - if(!one_taken) { + if(!render_running) { lv_draw_dispatch_request(); } disp = lv_display_get_next(disp); @@ -223,7 +223,7 @@ bool lv_draw_dispatch_layer(struct _lv_display_t * disp, lv_layer_t * layer) t = t_next; } - bool one_taken = false; + bool render_running = false; /*This layer is ready, enable blending its buffer*/ if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) { @@ -261,17 +261,13 @@ bool lv_draw_dispatch_layer(struct _lv_display_t * disp, lv_layer_t * layer) lv_draw_unit_t * u = _draw_info.unit_head; while(u) { int32_t taken_cnt = u->dispatch_cb(u, layer); - if(taken_cnt < 0) { - break; - } - if(taken_cnt > 0) one_taken = true; + if(taken_cnt >= 0) render_running = true; u = u->next; } } } - return one_taken; - + return render_running; } void lv_draw_dispatch_wait_for_request(void) diff --git a/src/draw/lv_draw.h b/src/draw/lv_draw.h index 7ea0ac5fa7..df06b629a9 100644 --- a/src/draw/lv_draw.h +++ b/src/draw/lv_draw.h @@ -117,9 +117,13 @@ typedef struct _lv_draw_unit_t { * A draw task should be assign only if the draw unit can draw it too * @param draw_unit pointer to the draw unit * @param layer pointer to a layer on which the draw task should be drawn - * @return >=0: The number of taken draw task - * -1: There where no available draw tasks at all. - * Also means to no call the dispatcher of the other draw units as there is no draw task to take + * @return >=0: The number of taken draw task: + * 0 means the task has not yet been completed. + * 1 means a new task has been accepted. + * -1: The draw unit wanted to work on a task but couldn't do that + * due to some errors (e.g. out of memory). + * It signals that LVGL should call the dispatcher later again + * to let draw unit try to start the rendering again. */ int32_t (*dispatch_cb)(struct _lv_draw_unit_t * draw_unit, struct _lv_layer_t * layer); diff --git a/src/draw/sw/lv_draw_sw.c b/src/draw/sw/lv_draw_sw.c index d07d4ecdb4..dee466746e 100644 --- a/src/draw/sw/lv_draw_sw.c +++ b/src/draw/sw/lv_draw_sw.c @@ -95,6 +95,14 @@ static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit) { #if LV_USE_OS lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; + + LV_LOG_INFO("cancel software rendering thread"); + draw_sw_unit->exit_status = true; + + if(draw_sw_unit->inited) { + lv_thread_sync_signal(&draw_sw_unit->sync); + } + return lv_thread_delete(&draw_sw_unit->thread); #else LV_UNUSED(draw_unit); @@ -128,7 +136,7 @@ static int32_t lv_draw_sw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * laye #if LV_USE_OS /*Let the render thread work*/ - lv_thread_sync_signal(&draw_sw_unit->sync); + if(draw_sw_unit->inited) lv_thread_sync_signal(&draw_sw_unit->sync); #else execute_drawing(draw_sw_unit); @@ -148,12 +156,21 @@ static void render_thread_cb(void * ptr) lv_draw_sw_unit_t * u = ptr; lv_thread_sync_init(&u->sync); + u->inited = true; while(1) { while(u->task_act == NULL) { + if(u->exit_status) { + break; + } lv_thread_sync_wait(&u->sync); } + if(u->exit_status) { + LV_LOG_INFO("ready to exit software rendering thread"); + break; + } + execute_drawing(u); /*Cleanup*/ @@ -163,6 +180,10 @@ static void render_thread_cb(void * ptr) /*The draw unit is free now. Request a new dispatching as it can get a new task*/ lv_draw_dispatch_request(); } + + u->inited = false; + lv_thread_sync_delete(&u->sync); + LV_LOG_INFO("exit software rendering thread"); } #endif diff --git a/src/draw/sw/lv_draw_sw.h b/src/draw/sw/lv_draw_sw.h index 19b507afe1..a51c7df836 100644 --- a/src/draw/sw/lv_draw_sw.h +++ b/src/draw/sw/lv_draw_sw.h @@ -36,6 +36,8 @@ typedef struct { #if LV_USE_OS lv_thread_sync_t sync; lv_thread_t thread; + volatile bool inited; + volatile bool exit_status; #endif uint32_t idx; } lv_draw_sw_unit_t; diff --git a/src/osal/lv_pthread.c b/src/osal/lv_pthread.c index df89259df0..68676c9467 100644 --- a/src/osal/lv_pthread.c +++ b/src/osal/lv_pthread.c @@ -51,8 +51,12 @@ lv_result_t lv_thread_init(lv_thread_t * thread, lv_thread_prio_t prio, void (*c lv_result_t lv_thread_delete(lv_thread_t * thread) { - LV_UNUSED(thread); - /*How?*/ + int ret = pthread_join(thread->thread, NULL); + if(ret != 0) { + LV_LOG_WARN("Error: %d", ret); + return LV_RESULT_INVALID; + } + return LV_RESULT_OK; }