mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-24 00:07:03 +08:00
feat(draw_sw): have only one SW draw unit with multiple threads internally (#7899)
This commit is contained in:
committed by
GitHub
parent
b4f256a40e
commit
90dcc889b2
@@ -353,7 +353,7 @@ static int32_t dispatch_cb(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DMA2D);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_DMA2D);
|
||||
if(t == NULL) {
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
}
|
||||
|
||||
+43
-30
@@ -32,7 +32,8 @@
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check);
|
||||
static void lv_cleanup_task(lv_draw_task_t * t, lv_display_t * disp);
|
||||
static void cleanup_task(lv_draw_task_t * t, lv_display_t * disp);
|
||||
static lv_draw_task_t * get_first_available_task(lv_layer_t * layer);
|
||||
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
|
||||
static inline uint32_t get_layer_size_kb(uint32_t size_byte)
|
||||
@@ -231,7 +232,7 @@ bool lv_draw_dispatch_layer(lv_display_t * disp, lv_layer_t * layer)
|
||||
while(t) {
|
||||
t_next = t->next;
|
||||
if(t->state == LV_DRAW_TASK_STATE_READY) {
|
||||
lv_cleanup_task(t, disp);
|
||||
cleanup_task(t, disp);
|
||||
if(t_prev != NULL)
|
||||
t_prev->next = t_next;
|
||||
else
|
||||
@@ -309,37 +310,20 @@ uint32_t lv_draw_get_unit_count(void)
|
||||
return _draw_info.unit_cnt;
|
||||
}
|
||||
|
||||
lv_draw_task_t * lv_draw_get_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id)
|
||||
{
|
||||
if(_draw_info.unit_cnt == 1) {
|
||||
return get_first_available_task(layer);
|
||||
}
|
||||
else {
|
||||
return lv_draw_get_next_available_task(layer, t_prev, draw_unit_id);
|
||||
}
|
||||
}
|
||||
|
||||
lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
|
||||
/* If there is only 1 draw unit the task can be consumed linearly as
|
||||
* they are added in the correct order. However, it can happen that
|
||||
* there is a `LV_DRAW_TASK_TYPE_LAYER` which can be blended only when
|
||||
* all its tasks are ready. As other areas might be on top of that
|
||||
* layer-to-blend don't skip it. Instead stop there, so that the
|
||||
* draw tasks of that layer can be consumed and can be finished.
|
||||
* After that this layer-to-blenf will have `LV_DRAW_TASK_STATE_QUEUED`
|
||||
* so it can be blended normally.*/
|
||||
if(_draw_info.unit_cnt <= 1) {
|
||||
lv_draw_task_t * t = layer->draw_task_head;
|
||||
while(t) {
|
||||
/*Not queued yet, leave this layer while the first task will be queued*/
|
||||
if(t->state != LV_DRAW_TASK_STATE_QUEUED) {
|
||||
t = NULL;
|
||||
break;
|
||||
}
|
||||
/*It's a supported and queued task, process it*/
|
||||
else {
|
||||
break;
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
LV_PROFILER_DRAW_END;
|
||||
return t;
|
||||
}
|
||||
|
||||
/*Handle the case of multiply draw units*/
|
||||
|
||||
/*If the first task is screen sized, there cannot be independent areas*/
|
||||
if(layer->draw_task_head) {
|
||||
@@ -554,7 +538,7 @@ static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check)
|
||||
* @param t pointer to a draw task
|
||||
* @param disp pointer to a display on which the task was drawn
|
||||
*/
|
||||
static void lv_cleanup_task(lv_draw_task_t * t, lv_display_t * disp)
|
||||
static void cleanup_task(lv_draw_task_t * t, lv_display_t * disp)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
/*If it was layer drawing free the layer too*/
|
||||
@@ -607,3 +591,32 @@ static void lv_cleanup_task(lv_draw_task_t * t, lv_display_t * disp)
|
||||
lv_free(t);
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
static lv_draw_task_t * get_first_available_task(lv_layer_t * layer)
|
||||
{
|
||||
LV_PROFILER_DRAW_BEGIN;
|
||||
/* If there is only 1 draw unit the task can be consumed linearly as
|
||||
* they are added in the correct order. However, it can happen that
|
||||
* there is a `LV_DRAW_TASK_TYPE_LAYER` which can be blended only when
|
||||
* all its tasks are ready. As other areas might be on top of that
|
||||
* layer-to-blend don't skip it. Instead stop there, so that the
|
||||
* draw tasks of that layer can be consumed and can be finished.
|
||||
* After that this layer-to-blenf will have `LV_DRAW_TASK_STATE_QUEUED`
|
||||
* so it can be blended normally.*/
|
||||
lv_draw_task_t * t = layer->draw_task_head;
|
||||
while(t) {
|
||||
/*Not queued yet, leave this layer while the first task is queued*/
|
||||
if(t->state != LV_DRAW_TASK_STATE_QUEUED) {
|
||||
t = NULL;
|
||||
break;
|
||||
}
|
||||
/*It's a supported and queued task, process it*/
|
||||
else {
|
||||
break;
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
|
||||
LV_PROFILER_DRAW_END;
|
||||
return t;
|
||||
}
|
||||
|
||||
+13
-3
@@ -199,11 +199,21 @@ void lv_draw_dispatch_request(void);
|
||||
uint32_t lv_draw_get_unit_count(void);
|
||||
|
||||
/**
|
||||
* Find and available draw task
|
||||
* @param layer the draw ctx to search in
|
||||
* If there is only one draw unit check the first draw task if it's available.
|
||||
* If there are multiple draw units call `lv_draw_get_next_available_task` to find a task.
|
||||
* @param layer the draw layer to search in
|
||||
* @param t_prev continue searching from this task
|
||||
* @param draw_unit_id check the task where `preferred_draw_unit_id` equals this value or `LV_DRAW_UNIT_NONE`
|
||||
* @return tan available draw task or NULL if there is no any
|
||||
* @return an available draw task or NULL if there is not any
|
||||
*/
|
||||
lv_draw_task_t * lv_draw_get_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id);
|
||||
|
||||
/**
|
||||
* Find and available draw task
|
||||
* @param layer the draw layer to search in
|
||||
* @param t_prev continue searching from this task
|
||||
* @param draw_unit_id check the task where `preferred_draw_unit_id` equals this value or `LV_DRAW_UNIT_NONE`
|
||||
* @return an available draw task or NULL if there is not any
|
||||
*/
|
||||
lv_draw_task_t * lv_draw_get_next_available_task(lv_layer_t * layer, lv_draw_task_t * t_prev, uint8_t draw_unit_id);
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ static int32_t nema_gfx_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_NEMA_GFX);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_NEMA_GFX);
|
||||
|
||||
/* Return 0 is no selection, some tasks can be supported by other units. */
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_NEMA_GFX)
|
||||
|
||||
@@ -194,7 +194,7 @@ static int32_t _g2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_G2D);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_G2D);
|
||||
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_G2D)
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
@@ -314,4 +314,4 @@ static void _g2d_render_thread_cb(void * ptr)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
#endif /*LV_USE_DRAW_G2D*/
|
||||
|
||||
@@ -323,7 +323,7 @@ static int32_t _pxp_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_PXP);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_PXP);
|
||||
|
||||
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP)
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
@@ -300,7 +300,7 @@ static int32_t _vglite_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
return 0;
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_VGLITE);
|
||||
|
||||
if(t == NULL)
|
||||
return LV_DRAW_UNIT_IDLE;
|
||||
|
||||
@@ -178,7 +178,7 @@ static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
if(draw_opengles_unit->task_act) return 0;
|
||||
|
||||
lv_draw_task_t * t = NULL;
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_OPENGLES);
|
||||
t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_OPENGLES);
|
||||
if(t == NULL) return -1;
|
||||
|
||||
unsigned int texture = layer_get_texture(layer);
|
||||
|
||||
@@ -357,10 +357,10 @@ static int32_t lv_draw_dave2d_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t *
|
||||
if(draw_dave2d_unit->task_act) return 0;
|
||||
|
||||
lv_draw_task_t * t = NULL;
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
|
||||
t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
|
||||
while(t && t->preferred_draw_unit_id != DRAW_UNIT_ID_DAVE2D) {
|
||||
t->state = LV_DRAW_TASK_STATE_READY;
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
|
||||
t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_DAVE2D);
|
||||
}
|
||||
|
||||
if(t == NULL) {
|
||||
|
||||
@@ -142,7 +142,7 @@ static int32_t dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
if(draw_sdl_unit->task_act) return 0;
|
||||
|
||||
lv_draw_task_t * t = NULL;
|
||||
t = lv_draw_get_next_available_task(layer, NULL, DRAW_UNIT_ID_SDL);
|
||||
t = lv_draw_get_available_task(layer, NULL, DRAW_UNIT_ID_SDL);
|
||||
if(t == NULL) return -1;
|
||||
|
||||
lv_display_t * disp = lv_refr_get_disp_refreshing();
|
||||
|
||||
+300
-232
File diff suppressed because it is too large
Load Diff
@@ -31,14 +31,22 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_draw_sw_unit_t {
|
||||
lv_draw_unit_t base_unit;
|
||||
typedef struct {
|
||||
lv_draw_task_t * task_act;
|
||||
#if LV_USE_OS
|
||||
lv_thread_sync_t sync;
|
||||
lv_thread_t thread;
|
||||
lv_thread_sync_t sync;
|
||||
lv_draw_unit_t * draw_unit;
|
||||
uint32_t idx;
|
||||
volatile bool inited;
|
||||
volatile bool exit_status;
|
||||
} lv_draw_sw_thread_dsc_t;
|
||||
|
||||
struct _lv_draw_sw_unit_t {
|
||||
lv_draw_unit_t base_unit;
|
||||
#if LV_USE_OS
|
||||
lv_draw_sw_thread_dsc_t thread_dscs[LV_DRAW_SW_DRAW_UNIT_CNT];
|
||||
#else
|
||||
lv_draw_task_t * task_act;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ static int32_t draw_dispatch(lv_draw_unit_t * draw_unit, lv_layer_t * layer)
|
||||
}
|
||||
|
||||
/* Try to get an ready to draw. */
|
||||
lv_draw_task_t * t = lv_draw_get_next_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID);
|
||||
lv_draw_task_t * t = lv_draw_get_available_task(layer, NULL, VG_LITE_DRAW_UNIT_ID);
|
||||
|
||||
/* Return 0 is no selection, some tasks can be supported by other units. */
|
||||
if(!t || t->preferred_draw_unit_id != VG_LITE_DRAW_UNIT_ID) {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <memory.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include "tvgCommon.h"
|
||||
|
||||
namespace tvg
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user