1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

refactor(display): use draw_buf_t for display (#5204)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu 2024-01-10 17:54:56 +08:00 committed by GitHub
parent a299242b34
commit ed99a21016
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 122 additions and 90 deletions

View File

@ -22,7 +22,8 @@ If you are updating a v8 project to v9, special care must be taken as some parts
So pay extra attention to these:
- :cpp:func:`lv_display_set_draw_buffers(display, buf1, buf2, buf_size_byte, mode)` is more or less the equivalent of ``lv_disp_draw_buf_init(&draw_buf_dsc, buf1, buf2, buf_size_px)`` from v8, however in **v9 the buffer size is set in bytes**.
- :cpp:func:`lv_display_set_draw_buffers(display, buf1, buf2)` is more or less the equivalent of ``lv_disp_draw_buf_init(&draw_buf_dsc, buf1, buf2, buf_size_px)`` from v8, however in **v9 the buffer type is lv_draw_buf_t**.
- Make sure to call :cpp:func:`lv_display_set_render_mode(display, mode)` to set correct render mode.
- In v9 ``lv_color_t`` is always RGB888 regardless of ``LV_COLOR_DEPTH``.
- ``lv_conf.h`` has been changed a lot, so don't forget to update it from ``lv_conf_template.h``
- Be sure ``<stdint.h>`` is **not** included in ``lv_conf.h``. In v9 we have some assembly parts for even better performance and a random include there would mess up the assembly part.
@ -78,9 +79,10 @@ Display API
lv_display_t * disp = lv_display_create(hor_res, ver_res)
lv_display_set_flush_cb(disp, flush_cb);
lv_display_set_draw_buffers(disp, buf1, buf2, buf_size_in_bytes, mode);
lv_display_set_draw_buffers(disp, buf1, buf2);
lv_display_set_render_mode(disp, mode);
- Note that now **buf size is in bytes and not pixels**
- Note that now **draw buffer can be malloced by `lv_draw_buf_create` or initialized by `lv_draw_buf_init`**
- ``mode`` can be:
- ``LV_DISPLAY_RENDER_MODE_PARTIAL`` This way the buffers can be

View File

@ -345,7 +345,8 @@ void _lv_display_refr_timer(lv_timer_t * tmr)
return;
}
if(disp_refr->buf_act == NULL || disp_refr->buf_act->data == NULL || disp_refr->buf_act->data_size == 0) {
lv_draw_buf_t * buf_act = disp_refr->buf_act;
if(!(buf_act && buf_act->data && buf_act->data_size)) {
LV_LOG_WARN("No draw buffer");
return;
}
@ -475,10 +476,10 @@ static void refr_sync_areas(void)
/*The buffers are already swapped.
*So the active buffer is the off screen buffer where LVGL will render*/
void * buf_off_screen = disp_refr->buf_act->data;
void * buf_on_screen = disp_refr->buf_act == &disp_refr->buf_1
? disp_refr->buf_2.data
: disp_refr->buf_1.data;
lv_draw_buf_t * on_screen = disp_refr->buf_act;
lv_draw_buf_t * off_screen = disp_refr->buf_act == disp_refr->buf_1 ? disp_refr->buf_2 : disp_refr->buf_1;
void * buf_off_screen = on_screen->data;
void * buf_on_screen = off_screen->data;
uint32_t hor_res = lv_display_get_horizontal_resolution(disp_refr);
uint32_t ver_res = lv_display_get_vertical_resolution(disp_refr);
@ -518,10 +519,14 @@ static void refr_sync_areas(void)
}
}
lv_area_t disp_area = {0, 0, (int32_t)hor_res - 1, (int32_t)ver_res - 1};
/*Copy sync areas (if any remaining)*/
for(sync_area = _lv_ll_get_head(&disp_refr->sync_areas); sync_area != NULL;
sync_area = _lv_ll_get_next(&disp_refr->sync_areas, sync_area)) {
/**
* @todo Resize SDL window will trigger crash because of sync_area is larger than disp_area
*/
_lv_area_intersect(sync_area, sync_area, &disp_area);
lv_draw_buf_copy(
buf_off_screen, hor_res, ver_res, sync_area,
buf_on_screen, hor_res, ver_res, sync_area,
@ -1009,11 +1014,11 @@ static void draw_buf_flush(lv_display_t * disp)
}
/*If there are 2 buffers swap them. With direct mode swap only on the last area*/
if(lv_display_is_double_buffered(disp) && (disp->render_mode != LV_DISPLAY_RENDER_MODE_DIRECT || flushing_last)) {
if(disp->buf_act == &disp->buf_1) {
disp->buf_act = &disp->buf_2;
if(disp->buf_act == disp->buf_1) {
disp->buf_act = disp->buf_2;
}
else {
disp->buf_act = &disp->buf_1;
disp->buf_act = disp->buf_1;
}
}
}

View File

@ -66,6 +66,8 @@ typedef struct {
drmModePropertyPtr crtc_props[128];
drmModePropertyPtr conn_props[128];
drm_buffer_t drm_bufs[2]; /*DUMB buffers*/
lv_draw_buf_t buf1;
lv_draw_buf_t buf2;
} drm_dev_t;
/**********************
@ -154,8 +156,11 @@ void lv_linux_drm_set_file(lv_display_t * disp, const char * file, int64_t conne
int32_t width = drm_dev->mmWidth;
size_t buf_size = LV_MIN(drm_dev->drm_bufs[1].size, drm_dev->drm_bufs[0].size);
lv_display_set_draw_buffers(disp, drm_dev->drm_bufs[1].map, drm_dev->drm_bufs[0].map, buf_size,
LV_DISPLAY_RENDER_MODE_DIRECT);
lv_draw_buf_init(&drm_dev->buf1, drm_dev->drm_bufs[0].map, hor_res, ver_res, 0, buf_size);
lv_draw_buf_init(&drm_dev->buf2, drm_dev->drm_bufs[1].map, hor_res, ver_res, 0, buf_size);
lv_display_set_draw_buffers(disp, &drm_dev->buf1, &drm_dev->buf2);
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
lv_display_set_resolution(disp, hor_res, ver_res);
if(width) {

View File

@ -197,12 +197,13 @@ void lv_linux_fbdev_set_file(lv_display_t * disp, const char * file)
draw_buf_size *= ver_res;
}
lv_color_t * draw_buf = lv_malloc(draw_buf_size);
lv_color_t * draw_buf_2 = NULL;
lv_draw_buf_t * draw_buf = lv_draw_buf_create(hor_res, ver_res, LV_COLOR_FORMAT_NATIVE, 0);
lv_draw_buf_t * draw_buf_2 = NULL;
if(LV_LINUX_FBDEV_BUFFER_COUNT == 2) {
draw_buf_2 = lv_malloc(draw_buf_size);
draw_buf_2 = lv_draw_buf_create(hor_res, ver_res, LV_COLOR_FORMAT_NATIVE, 0);
}
lv_display_set_draw_buffers(disp, draw_buf, draw_buf_2, draw_buf_size, LV_LINUX_FBDEV_RENDER_MODE);
lv_display_set_draw_buffers(disp, draw_buf, draw_buf_2);
lv_display_set_render_mode(disp, LV_LINUX_FBDEV_RENDER_MODE);
lv_display_set_resolution(disp, hor_res, ver_res);
if(width) {

View File

@ -40,6 +40,9 @@ typedef struct {
void * mem;
void * mem2;
uint32_t mem2_yoffset;
lv_draw_buf_t buf1;
lv_draw_buf_t buf2;
} lv_nuttx_fb_t;
/**********************
@ -123,16 +126,24 @@ int lv_nuttx_fbdev_set_file(lv_display_t * disp, const char * file)
goto errout;
}
uint32_t w = dsc->vinfo.xres;
uint32_t h = dsc->vinfo.yres;
uint32_t stride = dsc->pinfo.stride;
uint32_t data_size = h * stride;
lv_draw_buf_init(&dsc->buf1, w, h, LV_COLOR_FORMAT_NATIVE, stride, dsc->mem, data_size);
/* double buffer mode */
if(dsc->pinfo.yres_virtual == (dsc->vinfo.yres * 2)) {
if((ret = fbdev_init_mem2(dsc)) < 0) {
goto errout;
}
lv_draw_buf_init(&dsc->buf2, w, h, LV_COLOR_FORMAT_NATIVE, stride, dsc->mem2, data_size);
}
lv_display_set_draw_buffers(disp, dsc->mem, dsc->mem2,
(dsc->pinfo.stride * dsc->vinfo.yres), LV_DISP_RENDER_MODE_DIRECT);
lv_display_set_draw_buffers(disp, &dsc->buf1, &dsc->buf2);
lv_display_set_render_mode(disp, LV_DISP_RENDER_MODE_DIRECT);
lv_display_set_resolution(disp, dsc->vinfo.xres, dsc->vinfo.yres);
lv_timer_set_cb(disp->refr_timer, display_refr_timer_cb);
@ -205,7 +216,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * colo
/* double framebuffer */
if(dsc->mem2 != NULL) {
if(disp->buf_act == &disp->buf_1) {
if(disp->buf_act == disp->buf_1) {
dsc->pinfo.yoffset = 0;
}
else {

View File

@ -216,6 +216,7 @@ static void display_release_cb(lv_event_t * e)
/* clear display buffer */
if(disp->buf_1) {
# warning "fix me"
lv_free(disp->buf_1);
disp->buf_1 = NULL;
}

View File

@ -32,9 +32,10 @@ typedef struct {
SDL_Window * window;
SDL_Renderer * renderer;
SDL_Texture * texture;
uint8_t * fb1;
uint8_t * fb2;
uint8_t * fb_act;
lv_draw_buf_t * buf1;
lv_draw_buf_t * buf2;
lv_draw_buf_t * buf_act;
void * fb_full;
uint8_t zoom;
uint8_t ignore_size_chg;
} lv_sdl_window_t;
@ -104,27 +105,24 @@ lv_display_t * lv_sdl_window_create(int32_t hor_res, int32_t ver_res)
}
lv_display_add_event_cb(disp, release_disp_cb, LV_EVENT_DELETE, disp);
lv_display_set_driver_data(disp, dsc);
window_create(disp);
lv_display_set_flush_cb(disp, flush_cb);
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
uint8_t * buf1 = malloc(32 * 1024);
uint8_t * buf2 = NULL;
lv_draw_buf_t * buf1 = lv_draw_buf_create(1024, 4, LV_COLOR_FORMAT_NATIVE, 0);
lv_draw_buf_t * buf2 = NULL;
#if LV_SDL_BUF_COUNT == 2
buf2 = malloc(32 * 1024);
buf2 = lv_draw_buf_create(1024, 4, LV_COLOR_FORMAT_NATIVE, 0);
#endif
lv_display_set_draw_buffers(disp, buf1, buf2,
32 * 1024, LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_draw_buffers(disp, buf1, buf2);
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_PARTIAL);
dsc->buf_act = buf1;
dsc->buf1 = buf1;
dsc->buf2 = buf2;
}
/*LV_DISPLAY_RENDER_MODE_DIRECT or FULL */
else {
uint32_t stride = lv_draw_buf_width_to_stride(lv_display_get_horizontal_resolution(disp),
lv_display_get_color_format(disp));
lv_display_set_draw_buffers(disp, dsc->fb1, dsc->fb2, stride * lv_display_get_vertical_resolution(disp),
LV_SDL_RENDER_MODE);
}
lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
/*LV_DISPLAY_RENDER_MODE_DIRECT or FULL will have draw buffer created in texture_resize*/
window_create(disp);
dsc->buf_act = dsc->buf1;
lv_display_add_event_cb(disp, res_chg_event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);
return disp;
}
@ -188,7 +186,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
int32_t y;
uint8_t * fb_tmp = dsc->fb_act;
uint8_t * fb_tmp = dsc->fb_full;
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp));
uint32_t px_map_stride = lv_area_get_width(area) * px_size;
int32_t fb_stride = lv_display_get_horizontal_resolution(disp) * px_size;
@ -205,7 +203,9 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
* If it was the last part to refresh update the texture of the window.*/
if(lv_display_flush_is_last(disp)) {
if(LV_SDL_RENDER_MODE != LV_DISPLAY_RENDER_MODE_PARTIAL) {
dsc->fb_act = px_map;
#if LV_SDL_BUF_COUNT == 2
dsc->buf_act = px_map == dsc->buf1->data ? dsc->buf2 : dsc->buf1;
#endif
}
window_update(disp);
}
@ -284,11 +284,6 @@ static void window_create(lv_display_t * disp)
dsc->renderer = SDL_CreateRenderer(dsc->window, -1, SDL_RENDERER_SOFTWARE);
texture_resize(disp);
uint32_t px_size = lv_color_format_get_size(lv_display_get_color_format(disp));
lv_memset(dsc->fb1, 0xff, hor_res * ver_res * px_size);
#if LV_SDL_BUF_COUNT == 2
lv_memset(dsc->fb2, 0xff, hor_res * ver_res * px_size);
#endif
/*Some platforms (e.g. Emscripten) seem to require setting the size again */
SDL_SetWindowSize(dsc->window, hor_res * dsc->zoom, ver_res * dsc->zoom);
texture_resize(disp);
@ -298,9 +293,10 @@ static void window_update(lv_display_t * disp)
{
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
#if LV_USE_DRAW_SDL == 0
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp));
SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_act, stride);
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL)
SDL_UpdateTexture(dsc->texture, NULL, dsc->fb_full, dsc->buf_act->header.stride);
else
SDL_UpdateTexture(dsc->texture, NULL, dsc->buf_act->data, dsc->buf_act->header.stride);
SDL_RenderClear(dsc->renderer);
@ -312,24 +308,36 @@ static void window_update(lv_display_t * disp)
static void texture_resize(lv_display_t * disp)
{
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
int32_t hor_res = lv_display_get_horizontal_resolution(disp);
int32_t ver_res = lv_display_get_vertical_resolution(disp);
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, lv_display_get_color_format(disp));
lv_sdl_window_t * dsc = lv_display_get_driver_data(disp);
lv_color_format_t cf = lv_display_get_color_format(disp);
dsc->fb1 = realloc(dsc->fb1, stride * ver_res);
memset(dsc->fb1, 0x00, stride * ver_res);
uint32_t stride = lv_draw_buf_width_to_stride(hor_res, cf);
/*In partial mode, need a full buffer*/
if(LV_SDL_RENDER_MODE == LV_DISPLAY_RENDER_MODE_PARTIAL) {
dsc->fb_act = dsc->fb1;
dsc->fb_full = realloc(dsc->fb_full, stride * ver_res);
memset(dsc->fb_full, 0x00, stride * ver_res);
}
else {
/*Partial mode update doesn't need to update draw buffer.*/
if(LV_SDL_RENDER_MODE != LV_DISPLAY_RENDER_MODE_PARTIAL) {
if(dsc->buf1) lv_draw_buf_destroy(dsc->buf1);
dsc->buf1 = lv_draw_buf_create(hor_res, ver_res, cf, 0);
LV_ASSERT_NULL(dsc->buf1);
/*@todo lv_draw_buf_clear(dsc->buf1)*/
#if LV_SDL_BUF_COUNT == 2
dsc->fb2 = realloc(dsc->fb2, stride * ver_res);
memset(dsc->fb2, 0x00, stride * ver_res);
if(dsc->buf2) lv_draw_buf_destroy(dsc->buf2);
dsc->buf2 = lv_draw_buf_create(hor_res, ver_res, cf, 0);
LV_ASSERT_NULL(dsc->buf2);
#endif
lv_display_set_draw_buffers(disp, dsc->fb1, dsc->fb2, stride * ver_res, LV_SDL_RENDER_MODE);
dsc->buf_act = dsc->buf1;
lv_display_set_draw_buffers(disp, dsc->buf1, dsc->buf2);
lv_display_set_render_mode(disp, LV_SDL_RENDER_MODE);
}
if(dsc->texture) SDL_DestroyTexture(dsc->texture);
#if LV_COLOR_DEPTH == 32
@ -375,8 +383,8 @@ static void release_disp_cb(lv_event_t * e)
SDL_DestroyTexture(dsc->texture);
SDL_DestroyRenderer(dsc->renderer);
SDL_DestroyWindow(dsc->window);
if(dsc->fb1) free(dsc->fb1);
if(dsc->fb2) free(dsc->fb2);
if(dsc->buf1) lv_draw_buf_destroy(dsc->buf1);
if(dsc->buf2) lv_draw_buf_destroy(dsc->buf2);
lv_free(dsc);
lv_display_set_driver_data(disp, NULL);
}

View File

@ -386,25 +386,20 @@ int32_t lv_display_get_dpi(const lv_display_t * disp)
* BUFFERING
*--------------------*/
void lv_display_set_draw_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size_in_bytes,
lv_display_render_mode_t render_mode)
void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2)
{
if(disp == NULL) disp = lv_display_get_default();
if(disp == NULL) return;
LV_ASSERT_MSG(buf1 == lv_draw_buf_align(buf1, disp->color_format), "buf1 must be aligned");
disp->buf_1.data = buf1;
disp->buf_1.unaligned_data = buf1;
disp->buf_1.data_size = buf_size_in_bytes;
disp->buf_1 = buf1;
disp->buf_2 = buf2;
disp->buf_act = disp->buf_1;
}
if(buf2) {
LV_ASSERT_MSG(buf2 == lv_draw_buf_align(buf2, disp->color_format), "buf2 must be aligned");
disp->buf_2.data = buf2;
disp->buf_2.unaligned_data = buf2;
disp->buf_2.data_size = buf_size_in_bytes;
}
disp->buf_act = &disp->buf_1;
void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode)
{
if(disp == NULL) disp = lv_display_get_default();
if(disp == NULL) return;
disp->render_mode = render_mode;
}
@ -472,7 +467,7 @@ LV_ATTRIBUTE_FLUSH_READY bool lv_display_flush_is_last(lv_display_t * disp)
bool lv_display_is_double_buffered(lv_display_t * disp)
{
return disp->buf_2.data != NULL;
return disp->buf_2 != NULL;
}
/*---------------------

View File

@ -231,10 +231,15 @@ int32_t lv_display_get_dpi(const lv_display_t * disp);
* @param disp pointer to a display
* @param buf1 first buffer
* @param buf2 second buffer (can be `NULL`)
*/
void lv_display_set_draw_buffers(lv_display_t * disp, lv_draw_buf_t * buf1, lv_draw_buf_t * buf2);
/**
* Set display render mode
* @param disp pointer to a display
* @param render_mode LV_DISPLAY_RENDER_MODE_PARTIAL/DIRECT/FULL
*/
void lv_display_set_draw_buffers(lv_display_t * disp, void * buf1, void * buf2, uint32_t buf_size_in_bytes,
lv_display_render_mode_t render_mode);
void lv_display_set_render_mode(lv_display_t * disp, lv_display_render_mode_t render_mode);
/**
* Set the flush callback which will be called to copy the rendered image to the display.

View File

@ -58,8 +58,8 @@ struct _lv_display_t {
/*---------------------
* Buffering
*--------------------*/
lv_draw_buf_t buf_1;
lv_draw_buf_t buf_2;
lv_draw_buf_t * buf_1;
lv_draw_buf_t * buf_2;
/** Internal, used by the library*/
lv_draw_buf_t * buf_act;

View File

@ -155,6 +155,9 @@ lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, l
draw_buf->data = lv_draw_buf_align(data, cf);
draw_buf->unaligned_data = data;
draw_buf->data_size = data_size;
if(draw_buf->data != draw_buf->unaligned_data) {
LV_LOG_WARN("Data is not aligned, ignored");
}
return LV_RESULT_OK;
}

View File

@ -122,7 +122,6 @@ static inline void lv_obj_move_background(lv_obj_t * obj)
#define lv_disp_get_offset_y lv_display_get_offset_y
#define lv_disp_get_rotation lv_display_get_rotation
#define lv_disp_get_dpi lv_display_get_dpi
#define lv_disp_set_draw_buffers lv_display_set_draw_buffers
#define lv_disp_set_flush_cb lv_display_set_flush_cb
#define lv_disp_set_color_format lv_display_set_color_format
#define lv_disp_get_color_format lv_display_get_color_format

View File

@ -83,15 +83,10 @@ disp_drv = lv.display_create(WIDTH, HEIGHT)
disp_drv.set_flush_cb(flush)
disp_drv.set_color_format(lv.COLOR_FORMAT.RGB888)
buf = lv.draw_buf_create(WIDTH, HEIGHT, lv.COLOR_FORMAT.RGB888, 0)
color_size = lv.color_format_get_size(disp_drv.get_color_format())
buf = bytearray(WIDTH * HEIGHT * color_size)
disp_drv.set_draw_buffers(
buf,
None,
WIDTH * HEIGHT * color_size,
lv.DISPLAY_RENDER_MODE.FULL
)
disp_drv.set_draw_buffers(buf, None)
disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.FULL)
@test_func_wrapper

View File

@ -33,8 +33,10 @@ static void hal_init(void)
static lv_color32_t test_fb[(HOR_RES + LV_DRAW_BUF_STRIDE_ALIGN - 1) * VER_RES + LV_DRAW_BUF_ALIGN];
lv_display_t * disp = lv_display_create(HOR_RES, VER_RES);
lv_display_set_draw_buffers(disp, lv_draw_buf_align(test_fb, LV_COLOR_FORMAT_ARGB8888), NULL, HOR_RES * VER_RES,
LV_DISPLAY_RENDER_MODE_DIRECT);
static lv_draw_buf_t draw_buf;
lv_draw_buf_init(&draw_buf, HOR_RES, VER_RES, LV_COLOR_FORMAT_ARGB8888, 0, test_fb, sizeof(test_fb));
lv_display_set_draw_buffers(disp, &draw_buf, NULL);
lv_display_set_render_mode(disp, LV_DISPLAY_RENDER_MODE_DIRECT);
lv_display_set_flush_cb(disp, dummy_flush_cb);
lv_test_mouse_indev = lv_indev_create();