[dm][graphic] update graphic

1. Add FB_ACTIVATE_* cmd
2. Fixup the vsync
3. Update the graphic test

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GuEe-GUI
2026-08-07 09:26:42 +08:00
committed by Rbb666
parent 621a074a41
commit 871d9f5922
4 changed files with 879 additions and 246 deletions
+50 -10
View File
@@ -107,14 +107,25 @@ static rt_err_t plane_fb_remap(struct rt_graphic_plane *plane,
static rt_err_t plane_fb_pan_display(struct rt_graphic_plane *plane,
struct rt_device_rect_info *rect)
{
void *framebuffer_end = plane->framebuffer;
rt_size_t byte_per_pixel = plane->bits_per_pixel / 8;
rt_size_t offset, row_bytes, span;
framebuffer_end += rect->x * byte_per_pixel;
framebuffer_end += rect->y * plane->line_length;
framebuffer_end += rect->width * rect->height * byte_per_pixel;
if (!plane->framebuffer || !byte_per_pixel || !rect->width || !rect->height)
{
return -RT_EINVAL;
}
if (framebuffer_end < plane->framebuffer + plane->framebuffer_len)
row_bytes = rect->width * byte_per_pixel;
if (rect->x * byte_per_pixel + row_bytes > plane->line_length)
{
return -RT_EINVAL;
}
offset = rect->y * plane->line_length + rect->x * byte_per_pixel;
span = (rect->height - 1) * plane->line_length + row_bytes;
if (offset <= plane->framebuffer_len && span <= plane->framebuffer_len - offset)
{
return plane->ops->fb_pan_display(plane, rect);
}
@@ -203,6 +214,7 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t err = RT_EOK;
rt_bool_t need_schedule = RT_FALSE;
rt_bool_t wait_vsync = RT_FALSE;
struct rt_graphic_device *gdev = raw_to_graphic(dev);
_retry:
@@ -520,7 +532,7 @@ _retry:
case RTGRAPHIC_CTRL_WAIT_VSYNC:
if (gdev->ops->wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
wait_vsync = RT_TRUE;
}
break;
@@ -555,6 +567,8 @@ _retry:
var->yres = plane->height;
var->xres_virtual = plane->width;
var->yres_virtual = plane->height * (plane->framebuffer_len / plane->screen_len);
var->xoffset = plane->x;
var->yoffset = plane->y;
var->bits_per_pixel = plane->bits_per_pixel;
if (plane == gdev->primary_plane)
@@ -668,10 +682,16 @@ _retry:
for (int i = 0; i < plane->modes_nr; ++i)
{
/* Check supported and commit */
if (plane->modes[i] == mode && plane->mode != mode)
if (plane->modes[i] == mode)
{
err = plane_fb_remap(plane, mode, &rect);
err = RT_EOK;
if (plane->mode != mode)
{
err = plane_fb_remap(plane, mode, &rect);
}
break;
}
}
@@ -685,6 +705,11 @@ _retry:
err = plane_fb_pan_display(plane, &rect);
}
if (!err && (var->activate & FB_ACTIVATE_VBL) && gdev->ops->wait_vsync)
{
wait_vsync = RT_TRUE;
}
if (!err && var->rotate && plane->ops->prop_set)
{
err = plane->ops->prop_set(plane, RT_GRAPHIC_PLANE_PROP_ROTATE,
@@ -733,6 +758,11 @@ _retry:
fix->mmio_start = fix->smem_start;
fix->mmio_len = plane->screen_len;
fix->line_length = plane->line_length;
if (plane->ops->fb_pan_display && plane->framebuffer_len > plane->screen_len)
{
fix->ypanstep = 1;
}
}
else
{
@@ -769,6 +799,11 @@ _retry:
rect.height = var->yres;
err = plane_fb_pan_display(plane, &rect);
if (!err && (var->activate & FB_ACTIVATE_VBL) && gdev->ops->wait_vsync)
{
wait_vsync = RT_TRUE;
}
}
else
{
@@ -901,7 +936,7 @@ _retry:
case FBIO_WAITFORVSYNC:
if (gdev->ops->wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
wait_vsync = RT_TRUE;
}
break;
@@ -930,6 +965,11 @@ _retry:
spin_unlock(&gdev->lock);
if (!err && wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
}
return err;
}
+9
View File
@@ -40,6 +40,15 @@
#define FBIOGET_DISPINFO 0x4618
#define FBIO_WAITFORVSYNC 0x4620
/* fb_var_screeninfo.activate */
#define FB_ACTIVATE_NOW 0
#define FB_ACTIVATE_NXTOPEN 1
#define FB_ACTIVATE_TEST 2
#define FB_ACTIVATE_MASK 15
#define FB_ACTIVATE_VBL 16
#define FB_ACTIVATE_ALL 64
#define FB_ACTIVATE_FORCE 128
struct fb_bitfield
{
uint32_t offset; /* beginning of bitfield */
+63 -2
View File
@@ -11,6 +11,7 @@
#include <rtthread.h>
#include <rtdevice.h>
#include <drivers/lcd.h>
#include <drivers/misc.h>
#ifdef RT_USING_GRAPHIC
@@ -225,7 +226,10 @@ rt_err_t graphic_start(const char *gdev, int count)
{
rt_err_t err;
rt_uint8_t *vfb, *fb, *pixel, bpp;
rt_size_t frame_len, page_count, front_page;
struct rt_device_rect_info rect;
struct rt_device_graphic_info info;
struct fb_var_screeninfo var;
struct rt_device *dev = rt_device_find(gdev);
void (*conv_func)(rt_uint8_t r, rt_uint8_t g, rt_uint8_t b, void *pixel);
@@ -244,7 +248,21 @@ rt_err_t graphic_start(const char *gdev, int count)
goto _end;
}
if (!(vfb = rt_malloc(info.smem_len)))
if ((err = rt_device_control(dev, FBIOGET_VSCREENINFO, &var)))
{
goto _end;
}
frame_len = (rt_size_t)info.pitch * info.height;
page_count = frame_len ? info.smem_len / frame_len : 0;
if (!page_count)
{
err = -RT_EINVAL;
goto _end;
}
if (!(vfb = rt_malloc(frame_len)))
{
err = -RT_ENOMEM;
goto _end;
@@ -252,6 +270,19 @@ rt_err_t graphic_start(const char *gdev, int count)
bpp = info.bits_per_pixel / 8;
conv_func = conv_funcs[info.pixel_format];
front_page = var.yoffset / info.height;
if (page_count > 1)
{
/* Explicit page flips do not need the legacy periodic update timer. */
var.pixclock = 0;
var.activate = FB_ACTIVATE_NOW;
if ((err = rt_device_control(dev, FBIOPUT_VSCREENINFO, &var)))
{
goto _free_vfb;
}
}
for (int frame = 0; frame < count; ++frame)
{
@@ -275,9 +306,39 @@ rt_err_t graphic_start(const char *gdev, int count)
fb += info.pitch;
}
rt_memcpy(info.framebuffer, vfb, info.smem_len);
if (page_count > 1)
{
front_page = (front_page + 1) % page_count;
rt_memcpy((rt_uint8_t *)info.framebuffer + front_page * frame_len,
vfb, frame_len);
var.xoffset = 0;
var.yoffset = front_page * info.height;
var.activate = FB_ACTIVATE_VBL;
err = rt_device_control(dev, FBIOPAN_DISPLAY, &var);
}
else
{
rt_memcpy(info.framebuffer, vfb, frame_len);
rect.x = 0;
rect.y = 0;
rect.width = info.width;
rect.height = info.height;
err = rt_device_control(dev, RTGRAPHIC_CTRL_RECT_UPDATE, &rect);
if (!err)
{
err = rt_device_control(dev, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL);
}
}
if (err)
{
break;
}
}
_free_vfb:
rt_free(vfb);
_end:
File diff suppressed because it is too large Load Diff