修复: FB+视频共存 - compress(TRUE) + qua_gl_fill/transform

This commit is contained in:
zzh 2026-02-12 13:22:07 +08:00
parent 7466a2abd2
commit cc425d5bbe
3 changed files with 51 additions and 230 deletions

View File

@ -46,6 +46,7 @@ extern "C"
void *fbdev_req_mem(int size);
void *fbdev2_req_mem(int size);
int fbdev_get_actual_height(void);
void fbdev_set_hole(int x, int y, int width, int height);
void fbdev2_set_hole(int x, int y, int width, int height);
//

View File

@ -23,9 +23,7 @@
#include "system/qua_mm_system.h"
#include "filter/qua_mm_filter.h"
#include "quagl/qua_gl.h"
// #include "qua_los_2d.h" //函数不全
extern qua_mm_tde_device_t *g_tde_device_for_hole;
extern qua_mm_system_ops_t *g_sys_ops;
extern int g_screen_rotation;
@ -34,8 +32,6 @@ static qua_tde2_rect_t hole_rect, statusbar_rect;
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
static char *fbp = 0;
static uint32_t lvglAddr = 0;
/**********************
* MACROS
**********************/
@ -45,7 +41,6 @@ extern void fbdev_get_info(struct fb_var_screeninfo *pOutScreenInfo, struct fb_f
extern int fbdev_pan_disp(void);
static void fbdev_draw_hole();
//
void fbdev_init(void)
{
extern void fbdev_init_xd(void);
@ -54,34 +49,16 @@ void fbdev_init(void)
fbdev_get_info(&vinfo, &finfo);
fb_surface.data = fbp;
fb_surface.phy_addr = finfo.smem_start;
fb_surface.width = vinfo.xres;
fb_surface.height = vinfo.yres;
fb_surface.stride = vinfo.xres;
fb_surface.width = vinfo.xres_virtual;
fb_surface.height = vinfo.yres_virtual;
fb_surface.stride = vinfo.xres_virtual;
fb_surface.format = QUA_PIXEL_FMT_RGB_8888;
fb_surface.crop_x = 0;
fb_surface.crop_y = 0;
fb_surface.crop_w = vinfo.xres;
fb_surface.crop_h = vinfo.yres;
printf("设备信息: vinfo.xres:%d,vinfo.yres:%d \n", vinfo.xres, vinfo.yres);
if (g_screen_rotation == 1)
{
#ifdef CONFIG_XOS_FB_ROTATION
lvgl_surface.phy_addr = finfo.smem_start + finfo.smem_len / 2;
lvgl_surface.data = fbp + finfo.smem_len / 2;
lvgl_surface.width = vinfo.yres;
lvgl_surface.height = vinfo.xres;
lvgl_surface.stride = vinfo.yres;
lvgl_surface.format = QUA_PIXEL_FMT_RGB_8888;
lvgl_surface.crop_x = 0;
lvgl_surface.crop_y = 0;
lvgl_surface.crop_w = vinfo.yres;
lvgl_surface.crop_h = vinfo.xres;
#endif
}
else
{
lvgl_surface = fb_surface;
}
printf("fbdev_init: %dx%d smem_start=0x%lx\n", vinfo.xres, vinfo.yres, (unsigned long)finfo.smem_start);
lvgl_surface = fb_surface;
}
void fbdev_exit(void)
@ -94,19 +71,8 @@ void fbdev_exit(void)
void *fbdev_req_mem(int size)
{
// qm_effect_init_scr_info(lvgl_surface.width, lvgl_surface.height, lvgl_surface.data, lvgl_surface.phy_addr);
// return lvgl_surface.data;
void *buf = NULL;
int ret = posix_memalign(&buf, 64, size); // 64 字节对齐
if (ret != 0 || buf == NULL)
{
LV_LOG_ERROR("fbdev_req_mem malloc failed: ret=%d\n", ret);
return NULL;
}
memset(buf, 0, size);
return buf;
(void)size;
return lvgl_surface.data;
}
int fbdev_get_actual_height(void)
@ -136,16 +102,9 @@ void fbdev_set_statusbar(int x, int y, int width, int height)
static void fbdev_draw_hole()
{
QUA_S32 ret;
QUA_TDE_HANDLE handle;
qua_tde2_surface_t hole_surface = {};
if (hole_rect.width == 0 || hole_rect.height == 0)
return;
if (g_tde_device_for_hole == NULL)
return;
qua_tde2_rect_t tmp_rect = hole_rect;
QUA_S32 new_y = statusbar_rect.y_pos + statusbar_rect.height;
if (new_y > tmp_rect.y_pos)
@ -154,36 +113,15 @@ static void fbdev_draw_hole()
tmp_rect.y_pos = new_y;
}
hole_surface.phy_addr = lvgl_surface.phy_addr;
hole_surface.color_fmt = QUA_TDE2_COLOR_FMT_ARGB8888;
hole_surface.width = lvgl_surface.width;
hole_surface.height = lvgl_surface.height;
hole_surface.stride = lvgl_surface.width * 4;
hole_surface.alpha_max255 = QUA_TRUE;
hole_surface.fbc_compress = QUA_FALSE;
if (g_tde_device_for_hole->qua_tde2_begin_job == NULL ||
g_tde_device_for_hole->qua_tde2_quick_fill == NULL ||
g_tde_device_for_hole->qua_tde2_end_job == NULL)
return;
handle = g_tde_device_for_hole->qua_tde2_begin_job();
if (handle == QUA_FAILURE)
{
return;
}
ret = g_tde_device_for_hole->qua_tde2_quick_fill(handle, &hole_surface, &tmp_rect, 0x000000FF); // fill transparent blue color
if (ret != QUA_SUCCESS)
{
return;
}
ret = g_tde_device_for_hole->qua_tde2_end_job(handle, QUA_FALSE, QUA_TRUE, 5000);
if (ret != QUA_SUCCESS)
{
return;
}
fb_surface.crop_x = tmp_rect.x_pos;
fb_surface.crop_y = tmp_rect.y_pos;
fb_surface.crop_w = tmp_rect.width;
fb_surface.crop_h = tmp_rect.height;
qua_gl_fill(&fb_surface, 0);
fb_surface.crop_x = 0;
fb_surface.crop_y = 0;
fb_surface.crop_w = fb_surface.width;
fb_surface.crop_h = fb_surface.height;
}
/**
@ -201,8 +139,7 @@ void fbdev_flush(lv_display_t *drv, const lv_area_t *area, uint8_t *color_p)
return;
}
if (fbp == NULL ||
area->x2 < 0 ||
if (area->x2 < 0 ||
area->y2 < 0 ||
area->x1 > (int32_t)vinfo.xres - 1 ||
area->y1 > (int32_t)vinfo.yres - 1)
@ -211,166 +148,49 @@ void fbdev_flush(lv_display_t *drv, const lv_area_t *area, uint8_t *color_p)
return;
}
/* use qua_gl_transform to copy LVGL buffer to FB (compress mode compatible) */
lv_area_t buf_area = drv->layer_head->buf_area;
int32_t act_x1 = LV_MAX(area->x1, 0);
int32_t act_y1 = LV_MAX(area->y1, 0);
int32_t act_x2 = LV_MIN(area->x2, (int32_t)vinfo.xres - 1);
int32_t act_y2 = LV_MIN(area->y2, (int32_t)vinfo.yres - 1);
int32_t act_x2 = LV_MIN(area->x2, (int32_t)lvgl_surface.width - 1);
int32_t act_y2 = LV_MIN(area->y2, (int32_t)lvgl_surface.height - 1);
int32_t w = act_x2 - act_x1 + 1;
int32_t h = act_y2 - act_y1 + 1;
// 根据旋转角度处理像素映射
lv_display_rotation_t rotation = lv_display_get_rotation(drv);
qua_gl_surface_t src_surface = {};
qua_gl_transform_t trans = {};
if (rotation == LV_DISPLAY_ROTATION_180)
{
// 180度旋转从右下角开始绘制
for (int32_t y = 0; y < h; y++)
{
for (int32_t x = 0; x < w; x++)
{
// 计算源像素位置 (来自LVGL缓冲区)
uint32_t src_idx = (y * w + x) * 4;
src_surface.phy_addr = lvgl_surface.phy_addr;
src_surface.format = QUA_PIXEL_FMT_RGB_8888;
src_surface.width = buf_area.x2 - buf_area.x1 + 1;
src_surface.height = buf_area.y2 - buf_area.y1 + 1;
src_surface.stride = src_surface.width;
src_surface.crop_x = act_x1 - buf_area.x1;
src_surface.crop_y = act_y1 - buf_area.y1;
src_surface.crop_w = w;
src_surface.crop_h = h;
// 计算目标像素位置 (在帧缓冲区中)
int32_t dst_x = vinfo.xres - 1 - (act_x1 + x);
int32_t dst_y = vinfo.yres - 1 - (act_y1 + y);
fb_surface.crop_x = act_x1;
fb_surface.crop_y = act_y1;
fb_surface.crop_w = w;
fb_surface.crop_h = h;
if (dst_x >= 0 && dst_x < (int32_t)vinfo.xres &&
dst_y >= 0 && dst_y < (int32_t)vinfo.yres)
{
trans.conversion = 1;
QUA_BOOL ret = qua_gl_transform(&trans, &src_surface, &fb_surface);
if (ret == QUA_FALSE)
printf("%s, transform failed area=[%d,%d,%d,%d] buf=[%d,%d,%d,%d]\n", __func__,
area->x1, area->y1, area->x2, area->y2,
buf_area.x1, buf_area.y1, buf_area.x2, buf_area.y2);
uint8_t *dst_pixel = (uint8_t *)fbp +
(dst_y + vinfo.yoffset) * finfo.line_length +
(dst_x + vinfo.xoffset) * 4;
fb_surface.crop_x = 0;
fb_surface.crop_y = 0;
fb_surface.crop_w = fb_surface.width;
fb_surface.crop_h = fb_surface.height;
// 复制像素 (RGBA)
dst_pixel[0] = color_p[src_idx + 0]; // R
dst_pixel[1] = color_p[src_idx + 1]; // G
dst_pixel[2] = color_p[src_idx + 2]; // B
dst_pixel[3] = color_p[src_idx + 3]; // A
}
}
}
}
else if (rotation == LV_DISPLAY_ROTATION_90)
{
// 90度旋转逆时针旋转90度 (x,y) -> (y, width-1-x)
for (int32_t y = 0; y < h; y++)
{
for (int32_t x = 0; x < w; x++)
{
uint32_t src_idx = (y * w + x) * 4;
// 计算旋转后的坐标
int32_t dst_x = act_y1 + y;
int32_t dst_y = vinfo.yres - 1 - (act_x1 + x);
if (dst_x >= 0 && dst_x < (int32_t)vinfo.xres &&
dst_y >= 0 && dst_y < (int32_t)vinfo.yres)
{
uint8_t *dst_pixel = (uint8_t *)fbp +
(dst_y + vinfo.yoffset) * finfo.line_length +
(dst_x + vinfo.xoffset) * 4;
dst_pixel[0] = color_p[src_idx + 0]; // R
dst_pixel[1] = color_p[src_idx + 1]; // G
dst_pixel[2] = color_p[src_idx + 2]; // B
dst_pixel[3] = color_p[src_idx + 3]; // A
}
}
}
}
else if (rotation == LV_DISPLAY_ROTATION_270)
{
// 270度旋转逆时针旋转270度 (x,y) -> (height-1-y, x)
for (int32_t y = 0; y < h; y++)
{
for (int32_t x = 0; x < w; x++)
{
uint32_t src_idx = (y * w + x) * 4;
// 计算旋转后的坐标
int32_t dst_x = vinfo.xres - 1 - (act_y1 + y);
int32_t dst_y = act_x1 + x;
if (dst_x >= 0 && dst_x < (int32_t)vinfo.xres &&
dst_y >= 0 && dst_y < (int32_t)vinfo.yres)
{
uint8_t *dst_pixel = (uint8_t *)fbp +
(dst_y + vinfo.yoffset) * finfo.line_length +
(dst_x + vinfo.xoffset) * 4;
dst_pixel[0] = color_p[src_idx + 0]; // R
dst_pixel[1] = color_p[src_idx + 1]; // G
dst_pixel[2] = color_p[src_idx + 2]; // B
dst_pixel[3] = color_p[src_idx + 3]; // A
}
}
}
}
else
{
// 无旋转:正常处理
// ✅ 性能优化:如果是小区域刷新,使用单行拷贝;如果是大区域或全屏,使用更高效的内存拷贝
// 检查计算是否会超出帧缓冲区范围
uint32_t line_offset = (act_y1 + vinfo.yoffset) * finfo.line_length + (act_x1 + vinfo.xoffset) * 4;
if (line_offset >= finfo.smem_len)
{
lv_display_flush_ready(drv);
return;
}
uint8_t *fb_line = ((uint8_t *)fbp) + line_offset;
// 计算刷新区域大小,判断是否为小区域刷新
uint32_t refresh_area = w * h;
uint32_t screen_area = vinfo.xres * vinfo.yres;
if (refresh_area < screen_area / 4)
{
// 小区域刷新,使用单行拷贝
for (int32_t y = 0; y < h; y++)
{
// 检查当前行是否会超出缓冲区
if ((uint8_t *)fb_line - (uint8_t *)fbp + w * 4 > finfo.smem_len)
break;
memcpy(fb_line, color_p, w * 4); // copy one line
fb_line += finfo.line_length; // go to next line in framebuffer
color_p += w * 4; // go to next line in lvgl buffer
}
}
else
{
// 大区域刷新,使用更高效的内存拷贝
uint32_t fb_pitch = finfo.line_length / 4; // 每一行的像素数
uint32_t lvgl_pitch = w; // LVGL缓冲区每一行的像素数
uint32_t *fb_ptr = (uint32_t *)fb_line;
uint32_t *lvgl_ptr = (uint32_t *)color_p;
for (int32_t y = 0; y < h; y++)
{
// 检查当前行是否会超出缓冲区
if ((uint8_t *)fb_ptr - (uint8_t *)fbp + w * 4 > finfo.smem_len)
break;
memcpy(fb_ptr, lvgl_ptr, w * 4); // copy one line
fb_ptr += fb_pitch; // go to next line in framebuffer
lvgl_ptr += lvgl_pitch; // go to next line in lvgl buffer
}
}
}
// printf("2222刷新屏幕挖孔区域 \n");
if (lv_display_flush_is_last(drv))
{
// printf("刷新屏幕挖孔区域 \n");
fbdev_draw_hole(); // 播放视频打洞使用
fbdev_draw_hole();
fbdev_pan_disp();
}
lv_display_flush_ready(drv);

View File

@ -93,7 +93,6 @@ static QUA_S32 init_fyfb()
qua_fb_bitfield_t stB = {0, 8, 0};
qua_fb_bitfield_t stA = {24, 8, 0};
fb_device->show(fb_device, QUA_FALSE);
fb_device->compress(fb_device, QUA_FALSE);
qua_point_t position = {0, 0};
if (fb_device->put_origin != NULL)
@ -143,9 +142,9 @@ static QUA_S32 init_fyfb()
qua_fb_alpha_t alpha;
alpha.alpha_enable = QUA_TRUE;
alpha.alpha_channel = QUA_FALSE;
alpha.alpha_channel = QUA_TRUE;
alpha.alpha0 = 0;
alpha.alpha1 = 0;
alpha.alpha1 = 128;
alpha.global_alpha = 128;
alpha.reserved = 0;
if (fb_device->put_alpha(fb_device, &alpha) != QUA_SUCCESS)
@ -161,6 +160,7 @@ static QUA_S32 init_fyfb()
goto map_failed;
}
memset(pShowScreen, 0x00, finfo.smem_len);
fb_device->compress(fb_device, QUA_TRUE);
return QUA_SUCCESS;
map_failed:
fb_device->unmap(fb_device, pShowScreen, finfo.smem_len);