mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-24 00:07:03 +08:00
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:
+7
-11
@@ -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)
|
||||
|
||||
+7
-3
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user