mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 13:36:27 +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
|
#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) {
|
if(t == NULL) {
|
||||||
return LV_DRAW_UNIT_IDLE;
|
return LV_DRAW_UNIT_IDLE;
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-30
@@ -32,7 +32,8 @@
|
|||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
static bool is_independent(lv_layer_t * layer, lv_draw_task_t * t_check);
|
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
|
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
|
||||||
static inline uint32_t get_layer_size_kb(uint32_t size_byte)
|
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) {
|
while(t) {
|
||||||
t_next = t->next;
|
t_next = t->next;
|
||||||
if(t->state == LV_DRAW_TASK_STATE_READY) {
|
if(t->state == LV_DRAW_TASK_STATE_READY) {
|
||||||
lv_cleanup_task(t, disp);
|
cleanup_task(t, disp);
|
||||||
if(t_prev != NULL)
|
if(t_prev != NULL)
|
||||||
t_prev->next = t_next;
|
t_prev->next = t_next;
|
||||||
else
|
else
|
||||||
@@ -309,37 +310,20 @@ uint32_t lv_draw_get_unit_count(void)
|
|||||||
return _draw_info.unit_cnt;
|
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_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;
|
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 the first task is screen sized, there cannot be independent areas*/
|
||||||
if(layer->draw_task_head) {
|
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 t pointer to a draw task
|
||||||
* @param disp pointer to a display on which the task was drawn
|
* @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;
|
LV_PROFILER_DRAW_BEGIN;
|
||||||
/*If it was layer drawing free the layer too*/
|
/*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_free(t);
|
||||||
LV_PROFILER_DRAW_END;
|
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);
|
uint32_t lv_draw_get_unit_count(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and available draw task
|
* If there is only one draw unit check the first draw task if it's available.
|
||||||
* @param layer the draw ctx to search in
|
* 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 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`
|
* @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);
|
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;
|
return 0;
|
||||||
|
|
||||||
/* Try to get an ready to draw. */
|
/* 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. */
|
/* 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)
|
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;
|
return 0;
|
||||||
|
|
||||||
/* Try to get an ready to draw. */
|
/* 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)
|
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_G2D)
|
||||||
return LV_DRAW_UNIT_IDLE;
|
return LV_DRAW_UNIT_IDLE;
|
||||||
@@ -314,4 +314,4 @@ static void _g2d_render_thread_cb(void * ptr)
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
return 0;
|
||||||
|
|
||||||
/* Try to get an ready to draw. */
|
/* 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)
|
if(t == NULL || t->preferred_draw_unit_id != DRAW_UNIT_ID_PXP)
|
||||||
return LV_DRAW_UNIT_IDLE;
|
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;
|
return 0;
|
||||||
|
|
||||||
/* Try to get an ready to draw. */
|
/* 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)
|
if(t == NULL)
|
||||||
return LV_DRAW_UNIT_IDLE;
|
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;
|
if(draw_opengles_unit->task_act) return 0;
|
||||||
|
|
||||||
lv_draw_task_t * t = NULL;
|
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;
|
if(t == NULL) return -1;
|
||||||
|
|
||||||
unsigned int texture = layer_get_texture(layer);
|
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;
|
if(draw_dave2d_unit->task_act) return 0;
|
||||||
|
|
||||||
lv_draw_task_t * t = NULL;
|
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) {
|
while(t && t->preferred_draw_unit_id != DRAW_UNIT_ID_DAVE2D) {
|
||||||
t->state = LV_DRAW_TASK_STATE_READY;
|
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) {
|
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;
|
if(draw_sdl_unit->task_act) return 0;
|
||||||
|
|
||||||
lv_draw_task_t * t = NULL;
|
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;
|
if(t == NULL) return -1;
|
||||||
|
|
||||||
lv_display_t * disp = lv_refr_get_disp_refreshing();
|
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
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
struct _lv_draw_sw_unit_t {
|
typedef struct {
|
||||||
lv_draw_unit_t base_unit;
|
|
||||||
lv_draw_task_t * task_act;
|
lv_draw_task_t * task_act;
|
||||||
#if LV_USE_OS
|
|
||||||
lv_thread_sync_t sync;
|
|
||||||
lv_thread_t thread;
|
lv_thread_t thread;
|
||||||
|
lv_thread_sync_t sync;
|
||||||
|
lv_draw_unit_t * draw_unit;
|
||||||
|
uint32_t idx;
|
||||||
volatile bool inited;
|
volatile bool inited;
|
||||||
volatile bool exit_status;
|
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
|
#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. */
|
/* 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. */
|
/* 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) {
|
if(!t || t->preferred_draw_unit_id != VG_LITE_DRAW_UNIT_ID) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include "tvgCommon.h"
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user