fix(render): make parallel rendering work based on Nuttx Simulator (#4764)

Signed-off-by: YanXiaowei <yanxiaowei@xiaomi.com>
Co-authored-by: YanXiaowei <yanxiaowei@xiaomi.com>
This commit is contained in:
bjsylvia
2023-11-10 20:31:36 +08:00
committed by GitHub
parent ffe2c1528e
commit 17d1da62af
5 changed files with 44 additions and 17 deletions
+7 -11
View File
@@ -147,17 +147,17 @@ void lv_draw_finalize_task_creation(lv_layer_t * layer, lv_draw_task_t * t)
void lv_draw_dispatch(void) void lv_draw_dispatch(void)
{ {
LV_PROFILER_BEGIN; LV_PROFILER_BEGIN;
bool one_taken = false; bool render_running = false;
lv_display_t * disp = lv_display_get_next(NULL); lv_display_t * disp = lv_display_get_next(NULL);
while(disp) { while(disp) {
lv_layer_t * layer = disp->layer_head; lv_layer_t * layer = disp->layer_head;
while(layer) { while(layer) {
bool ret = lv_draw_dispatch_layer(disp, layer); if(lv_draw_dispatch_layer(disp, layer))
if(ret) one_taken = true; render_running = true;
layer = layer->next; layer = layer->next;
} }
if(!one_taken) { if(!render_running) {
lv_draw_dispatch_request(); lv_draw_dispatch_request();
} }
disp = lv_display_get_next(disp); 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; t = t_next;
} }
bool one_taken = false; bool render_running = false;
/*This layer is ready, enable blending its buffer*/ /*This layer is ready, enable blending its buffer*/
if(layer->parent && layer->all_tasks_added && layer->draw_task_head == NULL) { 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; lv_draw_unit_t * u = _draw_info.unit_head;
while(u) { while(u) {
int32_t taken_cnt = u->dispatch_cb(u, layer); int32_t taken_cnt = u->dispatch_cb(u, layer);
if(taken_cnt < 0) { if(taken_cnt >= 0) render_running = true;
break;
}
if(taken_cnt > 0) one_taken = true;
u = u->next; u = u->next;
} }
} }
} }
return one_taken; return render_running;
} }
void lv_draw_dispatch_wait_for_request(void) void lv_draw_dispatch_wait_for_request(void)
+7 -3
View File
@@ -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 * A draw task should be assign only if the draw unit can draw it too
* @param draw_unit pointer to the draw unit * @param draw_unit pointer to the draw unit
* @param layer pointer to a layer on which the draw task should be drawn * @param layer pointer to a layer on which the draw task should be drawn
* @return >=0: The number of taken draw task * @return >=0: The number of taken draw task:
* -1: There where no available draw tasks at all. * 0 means the task has not yet been completed.
* Also means to no call the dispatcher of the other draw units as there is no draw task to take * 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); int32_t (*dispatch_cb)(struct _lv_draw_unit_t * draw_unit, struct _lv_layer_t * layer);
+22 -1
View File
@@ -95,6 +95,14 @@ static int32_t lv_draw_sw_delete(lv_draw_unit_t * draw_unit)
{ {
#if LV_USE_OS #if LV_USE_OS
lv_draw_sw_unit_t * draw_sw_unit = (lv_draw_sw_unit_t *) draw_unit; 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); return lv_thread_delete(&draw_sw_unit->thread);
#else #else
LV_UNUSED(draw_unit); 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 #if LV_USE_OS
/*Let the render thread work*/ /*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 #else
execute_drawing(draw_sw_unit); execute_drawing(draw_sw_unit);
@@ -148,12 +156,21 @@ static void render_thread_cb(void * ptr)
lv_draw_sw_unit_t * u = ptr; lv_draw_sw_unit_t * u = ptr;
lv_thread_sync_init(&u->sync); lv_thread_sync_init(&u->sync);
u->inited = true;
while(1) { while(1) {
while(u->task_act == NULL) { while(u->task_act == NULL) {
if(u->exit_status) {
break;
}
lv_thread_sync_wait(&u->sync); lv_thread_sync_wait(&u->sync);
} }
if(u->exit_status) {
LV_LOG_INFO("ready to exit software rendering thread");
break;
}
execute_drawing(u); execute_drawing(u);
/*Cleanup*/ /*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*/ /*The draw unit is free now. Request a new dispatching as it can get a new task*/
lv_draw_dispatch_request(); lv_draw_dispatch_request();
} }
u->inited = false;
lv_thread_sync_delete(&u->sync);
LV_LOG_INFO("exit software rendering thread");
} }
#endif #endif
+2
View File
@@ -36,6 +36,8 @@ typedef struct {
#if LV_USE_OS #if LV_USE_OS
lv_thread_sync_t sync; lv_thread_sync_t sync;
lv_thread_t thread; lv_thread_t thread;
volatile bool inited;
volatile bool exit_status;
#endif #endif
uint32_t idx; uint32_t idx;
} lv_draw_sw_unit_t; } lv_draw_sw_unit_t;
+6 -2
View File
@@ -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_result_t lv_thread_delete(lv_thread_t * thread)
{ {
LV_UNUSED(thread); int ret = pthread_join(thread->thread, NULL);
/*How?*/ if(ret != 0) {
LV_LOG_WARN("Error: %d", ret);
return LV_RESULT_INVALID;
}
return LV_RESULT_OK; return LV_RESULT_OK;
} }