I wrote a hardware overlay driver for my laptop (a 10-year old one) and am trying the demo widget with it.
The issue is: if I do not put disp_drv.direct_mode = 1;
, the window of the demo widget is fast but is corrupted when I click “Analytics”. If setting it, all graphics are correct but the FPS is like 10fps at most.
My expectation: showing the graphics correct and fast, with both settings.
Thanks for any helps!
My config is:
static uint32_t vinfo_xres = 800;
static uint32_t vinfo_yres = 600;
static uint32_t vinfo_xoffset = 0;
static uint32_t vinfo_yoffset = 0;
static uint32_t vinfo_bits_per_pixel = 32;
static uint32_t finfo_line_length = vinfo_xres * 4; // bytes for each line, aka "stride"
My code is:
static void libgui_flush_cb(struct _lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
if(fbp == NULL ||
area->x2 < 0 ||
area->y2 < 0 ||
area->x1 > (int32_t)vinfo_xres - 1 ||
area->y1 > (int32_t)vinfo_yres - 1) {
lv_disp_flush_ready(disp_drv);
return;
}
// Truncate the area to the screen
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
int32_t act_x2 = area->x2 > (int32_t)vinfo_xres - 1 ? (int32_t)vinfo_xres - 1 : area->x2;
int32_t act_y2 = area->y2 > (int32_t)vinfo_yres - 1 ? (int32_t)vinfo_yres - 1 : area->y2;
lv_coord_t w = (act_x2 - act_x1 + 1);
long int location = 0;
long int byte_location = 0;
unsigned char bit_location = 0;
// 32 or 24 bit per pixel
if(vinfo_bits_per_pixel == 32 || vinfo_bits_per_pixel == 24) {
uint32_t * fbp32 = (uint32_t *)fbp;
int32_t y;
{
location = (act_x1 + vinfo_xoffset) + (act_y1 + vinfo_yoffset) * finfo_line_length / 4;
printf("[Superymk] <libgui_flush_cb> act_x1:%d, act_x2:%d, act_y1:%d, act_y2:%d, location_start:%ld\n",
act_x1, act_x2, act_y1, act_y2, location);
}
for(y = act_y1; y <= act_y2; y++) {
location = (act_x1 + vinfo_xoffset) + (y + vinfo_yoffset) * finfo_line_length / 4;
memcpy(&fbp32[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 4);
color_p += w;
}
}
// 16 bit per pixel
else if(vinfo_bits_per_pixel == 16) {
uint16_t * fbp16 = (uint16_t *)fbp;
int32_t y;
for(y = act_y1; y <= act_y2; y++) {
location = (act_x1 + vinfo_xoffset) + (y + vinfo_yoffset) * finfo_line_length / 2;
memcpy(&fbp16[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 2);
color_p += w;
}
}
// 8 bit per pixel
else if(vinfo_bits_per_pixel == 8) {
uint8_t * fbp8 = (uint8_t *)fbp;
int32_t y;
for(y = act_y1; y <= act_y2; y++) {
location = (act_x1 + vinfo_xoffset) + (y + vinfo_yoffset) * finfo_line_length;
memcpy(&fbp8[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1));
color_p += w;
}
}
// 1 bit per pixel
else if(vinfo_bits_per_pixel == 1) {
uint8_t * fbp8 = (uint8_t *)fbp;
int32_t x;
int32_t y;
for(y = act_y1; y <= act_y2; y++) {
for(x = act_x1; x <= act_x2; x++) {
location = (x + vinfo_xoffset) + (y + vinfo_yoffset) * vinfo_xres;
byte_location = location / 8; /* find the byte we need to change */
bit_location = location % 8; /* inside the byte found, find the bit we need to change */
fbp8[byte_location] &= ~(((uint8_t)(1)) << bit_location);
fbp8[byte_location] |= ((uint8_t)(color_p->full)) << bit_location;
color_p++;
}
color_p += area->x2 - act_x2;
}
} else {
/*Not supported bit per pixel*/
}
//May be some direct update command is required
//ret = ioctl(state->fd, FBIO_UPDATE, (unsigned long)((uintptr_t)rect));
lv_disp_flush_ready(disp_drv);
And init function is:
SAP_STATUS status = SUCCESS;
// Check: <cfg> must be valid
if (!cfg)
return EINVAL;
if(cfg->fb_vaddr == INVALID_VADDR)
return EINVAL;
// Check: No double init
if (disp)
return EINVAL;
// Initialize window canvas
// LittlevGL init
lv_init();
// Initialize a descriptor for the buffer
static lv_disp_draw_buf_t disp_buf;
lv_disp_draw_buf_init(&disp_buf, (void *)cfg->fb_vaddr, NULL, cfg->fb_width * cfg->fb_height);
fbp = (void *)cfg->fb_vaddr;
// Initialize and register a display driver
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.direct_mode = 1;
disp_drv.draw_buf = &disp_buf;
disp_drv.flush_cb = libgui_flush_cb;
disp_drv.hor_res = cfg->fb_width;
disp_drv.ver_res = cfg->fb_height;
disp = lv_disp_drv_register(&disp_drv);
if (!disp)
{
GUI_ERR("Init Lib-GUI error: Failed to init display!\n");
status = EINTERNAL;
goto init_disp_err;
}
//// Display configs
vinfo_xres = 800;
vinfo_yres = 600;
vinfo_xoffset = 0;
vinfo_yoffset = 0;
vinfo_bits_per_pixel = 32;
finfo_line_length = vinfo_xres * 4; // bytes for each line, aka "stride"
// Register keyboard
static lv_indev_drv_t kbd_drv;
lv_indev_drv_init(&kbd_drv); /*Basic initialization*/
kbd_drv.type = LV_INDEV_TYPE_KEYPAD;
kbd_drv.read_cb = libgui_keyboard_read;
kbd_indev = lv_indev_drv_register(&kbd_drv);
if (!kbd_indev)
{
GUI_ERR("Init Lib-GUI error: Failed to init keyboard!\n");
status = EINTERNAL;
goto init_kbd_err;
}
// Register mouse
static lv_indev_drv_t mouse_drv;
lv_indev_drv_init(&mouse_drv); /*Basic initialization*/
mouse_drv.type = LV_INDEV_TYPE_POINTER;
// This function will be called periodically (by the library) to get the mouse position and state
mouse_drv.read_cb = libgui_mouse_read;
mouse_indev = lv_indev_drv_register(&mouse_drv);
if (!mouse_indev)
{
GUI_ERR("Init Lib-GUI error: Failed to init mouse!\n");
status = EINTERNAL;
goto init_mouse_err;
}
//// Configure mouse
lines_per_wheel = cfg->lines_per_wheel;
// Set a cursor for the mouse
LV_IMG_DECLARE(mouse_cursor_icon)
cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
if (!cursor_obj)
{
GUI_ERR("Init Lib-GUI error: Failed to init cursor!\n");
status = EINTERNAL;
goto init_cursor_err;
}
lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
lv_indev_set_cursor(mouse_indev, cursor_obj); /*Connect the image object to the driver*/
/*Create a Demo*/
lv_demo_widgets();
GUI_INFO("Initialize Lib-GUI Success\n");
return SUCCESS;
init_cursor_err:
init_mouse_err:
init_kbd_err:
init_disp_err:
return status;
Screenshot (setting disp_drv.direct_mode = 1;
):
Screenshot (no disp_drv.direct_mode = 1;
):