Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 50 additions & 10 deletions components/drivers/graphic/graphic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

row_bytes = rect->width * byte_per_pixel;

if (framebuffer_end < plane->framebuffer + plane->framebuffer_len)
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);
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -520,7 +532,7 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
case RTGRAPHIC_CTRL_WAIT_VSYNC:
if (gdev->ops->wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
wait_vsync = RT_TRUE;
}
break;

Expand Down Expand Up @@ -555,6 +567,8 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
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)
Expand Down Expand Up @@ -668,10 +682,16 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)

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;
}
}

Expand All @@ -685,6 +705,11 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
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,
Expand Down Expand Up @@ -733,6 +758,11 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
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
{
Expand Down Expand Up @@ -769,6 +799,11 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
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
{
Expand Down Expand Up @@ -901,7 +936,7 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)
case FBIO_WAITFORVSYNC:
if (gdev->ops->wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
wait_vsync = RT_TRUE;
}
break;

Expand Down Expand Up @@ -930,6 +965,11 @@ static rt_err_t _graphic_control(rt_device_t dev, int cmd, void *args)

spin_unlock(&gdev->lock);

if (!err && wait_vsync)
{
err = gdev->ops->wait_vsync(gdev);
}

return err;
}

Expand Down
9 changes: 9 additions & 0 deletions components/drivers/include/drivers/lcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
65 changes: 63 additions & 2 deletions examples/test/dm_graphic_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <rtthread.h>
#include <rtdevice.h>

#include <drivers/lcd.h>
#include <drivers/misc.h>

#ifdef RT_USING_GRAPHIC
Expand Down Expand Up @@ -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);

Expand All @@ -244,14 +248,41 @@ 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;
}

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)
{
Expand All @@ -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:
Expand Down
Loading