video/fb: add vsync queue
refact vsync queue to support multi fb poll and overlay poll. Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com> Signed-off-by: rongyichang <rongyichang@xiaomi.com>
This commit is contained in:
parent
43ea7e65e1
commit
e578f3b20d
@ -50,6 +50,11 @@ config VIDEO_FB
|
||||
bool "Framebuffer character driver"
|
||||
default n
|
||||
|
||||
config VIDEO_FB_NPOLLWAITERS
|
||||
int "Video fb poll count of each layer"
|
||||
depends on VIDEO_FB
|
||||
default 2
|
||||
|
||||
config VIDEO_STREAM
|
||||
bool "Video Stream Support"
|
||||
default n
|
||||
|
@ -41,17 +41,30 @@
|
||||
#include <nuttx/video/fb.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/mm/circbuf.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define FB_NO_OVERLAY -1
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct fb_priv_s
|
||||
{
|
||||
int overlay; /* Overlay number */
|
||||
};
|
||||
|
||||
struct fb_paninfo_s
|
||||
{
|
||||
FAR struct circbuf_s buf; /* Pan buffer queued list */
|
||||
|
||||
/* Polling fds of waiting threads */
|
||||
|
||||
FAR struct pollfd *fds[CONFIG_VIDEO_FB_NPOLLWAITERS];
|
||||
};
|
||||
|
||||
/* This structure defines one framebuffer device. Note that which is
|
||||
* everything in this structure is constant data set up and initialization
|
||||
* time. Therefore, no there is requirement for serialized access to this
|
||||
@ -60,23 +73,21 @@
|
||||
|
||||
struct fb_chardev_s
|
||||
{
|
||||
FAR struct fb_vtable_s *vtable; /* Framebuffer interface */
|
||||
FAR struct pollfd *fds; /* Polling structure of waiting thread */
|
||||
uint8_t plane; /* Video plan number */
|
||||
volatile int pollcnt; /* Poll ready count */
|
||||
clock_t vsyncoffset; /* VSync offset ticks */
|
||||
struct wdog_s wdog; /* VSync offset timer */
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
int overlay; /* Overlay number */
|
||||
#endif
|
||||
mutex_t lock; /* Mutual exclusion */
|
||||
int16_t crefs; /* Number of open references */
|
||||
FAR struct fb_vtable_s *vtable; /* Framebuffer interface */
|
||||
uint8_t plane; /* Video plan number */
|
||||
clock_t vsyncoffset; /* VSync offset ticks */
|
||||
struct wdog_s wdog; /* VSync offset timer */
|
||||
mutex_t lock; /* Mutual exclusion */
|
||||
int16_t crefs; /* Number of open references */
|
||||
FAR struct fb_paninfo_s *paninfo; /* Pan info array */
|
||||
size_t paninfo_count; /* Pan info count */
|
||||
};
|
||||
|
||||
struct fb_panelinfo_s
|
||||
{
|
||||
FAR void *fbmem; /* Start of frame buffer memory */
|
||||
size_t fblen; /* Size of the framebuffer */
|
||||
uint8_t fbcount; /* Count of frame buffer */
|
||||
uint8_t bpp; /* Bits per pixel */
|
||||
};
|
||||
|
||||
@ -84,6 +95,13 @@ struct fb_panelinfo_s
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct pollfd **fb_get_free_pollfds(FAR struct fb_chardev_s *fb,
|
||||
int overlay);
|
||||
static FAR struct circbuf_s *fb_get_panbuf(FAR struct fb_chardev_s *fb,
|
||||
int overlay);
|
||||
static int fb_add_paninfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR const union fb_paninfo_u *info,
|
||||
int overlay);
|
||||
static int fb_open(FAR struct file *filep);
|
||||
static int fb_close(FAR struct file *filep);
|
||||
static ssize_t fb_read(FAR struct file *filep, FAR char *buffer,
|
||||
@ -97,7 +115,8 @@ static int fb_mmap(FAR struct file *filep,
|
||||
static int fb_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
|
||||
FAR struct fb_panelinfo_s *panelinfo);
|
||||
FAR struct fb_panelinfo_s *panelinfo,
|
||||
int overlay);
|
||||
static int fb_get_planeinfo(FAR struct fb_chardev_s *fb,
|
||||
FAR struct fb_planeinfo_s *pinfo,
|
||||
uint8_t display);
|
||||
@ -123,6 +142,93 @@ static const struct file_operations g_fb_fops =
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_get_free_pollfds
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct pollfd **fb_get_free_pollfds(FAR struct fb_chardev_s *fb,
|
||||
int overlay)
|
||||
{
|
||||
FAR struct fb_paninfo_s *paninfo;
|
||||
int id = overlay + 1;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(id >= 0 && id < fb->paninfo_count);
|
||||
|
||||
paninfo = &fb->paninfo[id];
|
||||
|
||||
for (i = 0; i < CONFIG_VIDEO_FB_NPOLLWAITERS; ++i)
|
||||
{
|
||||
if (!paninfo->fds[i])
|
||||
{
|
||||
return &paninfo->fds[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_get_panbuf
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct circbuf_s *fb_get_panbuf(FAR struct fb_chardev_s *fb,
|
||||
int overlay)
|
||||
{
|
||||
int id = overlay + 1;
|
||||
|
||||
DEBUGASSERT(id >= 0 && id < fb->paninfo_count);
|
||||
|
||||
return &(fb->paninfo[id].buf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_add_paninfo
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_add_paninfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR const union fb_paninfo_u *info,
|
||||
int overlay)
|
||||
{
|
||||
FAR struct circbuf_s *panbuf;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
irqstate_t flags;
|
||||
ssize_t ret;
|
||||
|
||||
DEBUGASSERT(vtable != NULL);
|
||||
|
||||
/* Prevent calling before getting the vtable. */
|
||||
|
||||
fb = vtable->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panbuf = fb_get_panbuf(fb, overlay);
|
||||
if (panbuf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable the interrupt when writing to the queue to
|
||||
* prevent it from being modified by the interrupted
|
||||
* thread during the writing process.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Write planeinfo information to the queue. */
|
||||
|
||||
ret = circbuf_write(panbuf, info, sizeof(union fb_paninfo_u));
|
||||
DEBUGASSERT(ret == sizeof(union fb_paninfo_u));
|
||||
|
||||
/* Re-enable interrupts */
|
||||
|
||||
leave_critical_section(flags);
|
||||
return ret <= 0 ? -ENOSPC : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_open
|
||||
****************************************************************************/
|
||||
@ -131,6 +237,7 @@ static int fb_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
int ret;
|
||||
|
||||
inode = filep->f_inode;
|
||||
@ -144,20 +251,34 @@ static int fb_open(FAR struct file *filep)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv = kmm_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (fb->crefs == 0)
|
||||
{
|
||||
if (fb->vtable->open != NULL)
|
||||
if (fb->vtable->open != NULL &&
|
||||
(ret = fb->vtable->open(fb->vtable)) < 0)
|
||||
{
|
||||
ret = fb->vtable->open(fb->vtable);
|
||||
goto err_fb;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
fb->crefs++;
|
||||
DEBUGASSERT(fb->crefs > 0);
|
||||
}
|
||||
fb->crefs++;
|
||||
DEBUGASSERT(fb->crefs > 0);
|
||||
|
||||
priv->overlay = FB_NO_OVERLAY;
|
||||
filep->f_priv = priv;
|
||||
|
||||
nxmutex_unlock(&fb->lock);
|
||||
return 0;
|
||||
|
||||
err_fb:
|
||||
kmm_free(priv);
|
||||
err_out:
|
||||
nxmutex_unlock(&fb->lock);
|
||||
return ret;
|
||||
}
|
||||
@ -170,12 +291,14 @@ static int fb_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
int ret;
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL);
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
ret = nxmutex_lock(&fb->lock);
|
||||
if (ret < 0)
|
||||
@ -195,6 +318,7 @@ static int fb_close(FAR struct file *filep)
|
||||
{
|
||||
DEBUGASSERT(fb->crefs > 0);
|
||||
fb->crefs--;
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&fb->lock);
|
||||
@ -209,6 +333,7 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
struct fb_panelinfo_s panelinfo;
|
||||
size_t start;
|
||||
size_t end;
|
||||
@ -221,10 +346,13 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
/* Get panel info */
|
||||
|
||||
ret = fb_get_panelinfo(fb, &panelinfo);
|
||||
ret = fb_get_panelinfo(fb, &panelinfo, priv->overlay);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -263,6 +391,7 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
struct fb_panelinfo_s panelinfo;
|
||||
size_t start;
|
||||
size_t end;
|
||||
@ -275,10 +404,13 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
/* Get panel info */
|
||||
|
||||
ret = fb_get_panelinfo(fb, &panelinfo);
|
||||
ret = fb_get_panelinfo(fb, &panelinfo, priv->overlay);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -322,6 +454,7 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
struct fb_panelinfo_s panelinfo;
|
||||
off_t newpos;
|
||||
int ret;
|
||||
@ -332,6 +465,9 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
/* Determine the new, requested file position */
|
||||
|
||||
@ -349,7 +485,7 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
|
||||
/* Get panel info */
|
||||
|
||||
ret = fb_get_panelinfo(fb, &panelinfo);
|
||||
ret = fb_get_panelinfo(fb, &panelinfo, priv->overlay);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -507,14 +643,15 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
case FBIO_SELECT_OVERLAY: /* Select video overlay */
|
||||
{
|
||||
struct fb_overlayinfo_s oinfo;
|
||||
FAR struct fb_priv_s *priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL &&
|
||||
DEBUGASSERT(priv != NULL && fb->vtable != NULL &&
|
||||
fb->vtable->getoverlayinfo != NULL);
|
||||
memset(&oinfo, 0, sizeof(oinfo));
|
||||
ret = fb->vtable->getoverlayinfo(fb->vtable, arg, &oinfo);
|
||||
if (ret == OK)
|
||||
if (ret >= 0)
|
||||
{
|
||||
fb->overlay = arg;
|
||||
priv->overlay = arg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -625,10 +762,18 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct fb_overlayinfo_s *oinfo =
|
||||
(FAR struct fb_overlayinfo_s *)((uintptr_t)arg);
|
||||
union fb_paninfo_u paninfo;
|
||||
|
||||
DEBUGASSERT(oinfo != 0 && fb->vtable != NULL &&
|
||||
fb->vtable->panoverlay != NULL);
|
||||
ret = fb->vtable->panoverlay(fb->vtable, oinfo);
|
||||
DEBUGASSERT(oinfo != 0 && fb->vtable != NULL);
|
||||
|
||||
memcpy(&paninfo, oinfo, sizeof(*oinfo));
|
||||
|
||||
if (fb->vtable->panoverlay != NULL)
|
||||
{
|
||||
fb->vtable->panoverlay(fb->vtable, oinfo);
|
||||
}
|
||||
|
||||
ret = fb_add_paninfo(fb->vtable, &paninfo, oinfo->overlay);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -676,15 +821,18 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct fb_planeinfo_s *pinfo =
|
||||
(FAR struct fb_planeinfo_s *)((uintptr_t)arg);
|
||||
union fb_paninfo_u paninfo;
|
||||
|
||||
DEBUGASSERT(pinfo != NULL && fb->vtable != NULL &&
|
||||
fb->vtable->pandisplay != NULL);
|
||||
ret = fb->vtable->pandisplay(fb->vtable, pinfo);
|
||||
fb->pollcnt--;
|
||||
DEBUGASSERT(pinfo != NULL && fb->vtable != NULL);
|
||||
|
||||
/* Check pan display overrun. */
|
||||
memcpy(&paninfo, pinfo, sizeof(*pinfo));
|
||||
|
||||
DEBUGASSERT(fb->pollcnt >= 0);
|
||||
if (fb->vtable->pandisplay != NULL)
|
||||
{
|
||||
fb->vtable->pandisplay(fb->vtable, pinfo);
|
||||
}
|
||||
|
||||
ret = fb_add_paninfo(fb->vtable, &paninfo, FB_NO_OVERLAY);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -844,6 +992,7 @@ static int fb_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
struct fb_panelinfo_s panelinfo;
|
||||
int ret;
|
||||
|
||||
@ -851,10 +1000,13 @@ static int fb_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map)
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
/* Get panel info */
|
||||
|
||||
ret = fb_get_panelinfo(fb, &panelinfo);
|
||||
ret = fb_get_panelinfo(fb, &panelinfo, priv->overlay);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -885,36 +1037,52 @@ static int fb_poll(FAR struct file *filep, struct pollfd *fds, bool setup)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
FAR struct fb_priv_s *priv;
|
||||
FAR struct circbuf_s *panbuf;
|
||||
FAR struct pollfd **pollfds;
|
||||
irqstate_t flags;
|
||||
int ret = OK;
|
||||
|
||||
/* Get the framebuffer instance */
|
||||
|
||||
inode = filep->f_inode;
|
||||
fb = inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
|
||||
DEBUGASSERT(fb->vtable != NULL && priv != NULL);
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (setup)
|
||||
{
|
||||
if (fb->fds == NULL)
|
||||
pollfds = fb_get_free_pollfds(fb, priv->overlay);
|
||||
if (pollfds == NULL)
|
||||
{
|
||||
fb->fds = fds;
|
||||
fds->priv = &fb->fds;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (fb->pollcnt > 0)
|
||||
*pollfds = fds;
|
||||
fds->priv = pollfds;
|
||||
|
||||
panbuf = fb_get_panbuf(fb, priv->overlay);
|
||||
if (!circbuf_is_full(panbuf))
|
||||
{
|
||||
poll_notify(&fb->fds, 1, POLLOUT);
|
||||
poll_notify(pollfds, 1, POLLOUT);
|
||||
}
|
||||
}
|
||||
else if (fds->priv)
|
||||
else if (fds->priv != NULL)
|
||||
{
|
||||
fb->fds = NULL;
|
||||
/* This is a request to tear down the poll. */
|
||||
|
||||
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
|
||||
*slot = NULL;
|
||||
fds->priv = NULL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
errout:
|
||||
leave_critical_section(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -922,18 +1090,20 @@ static int fb_poll(FAR struct file *filep, struct pollfd *fds, bool setup)
|
||||
****************************************************************************/
|
||||
|
||||
static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
|
||||
FAR struct fb_panelinfo_s *panelinfo)
|
||||
FAR struct fb_panelinfo_s *panelinfo,
|
||||
int overlay)
|
||||
{
|
||||
struct fb_planeinfo_s pinfo;
|
||||
struct fb_videoinfo_s vinfo;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
if (fb->overlay != FB_NO_OVERLAY)
|
||||
if (overlay != FB_NO_OVERLAY)
|
||||
{
|
||||
struct fb_overlayinfo_s oinfo;
|
||||
DEBUGASSERT(fb->vtable->getoverlayinfo != NULL);
|
||||
memset(&oinfo, 0, sizeof(oinfo));
|
||||
ret = fb->vtable->getoverlayinfo(fb->vtable, fb->overlay, &oinfo);
|
||||
ret = fb->vtable->getoverlayinfo(fb->vtable, overlay, &oinfo);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -941,9 +1111,11 @@ static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
|
||||
return ret;
|
||||
}
|
||||
|
||||
panelinfo->fbmem = oinfo.fbmem;
|
||||
panelinfo->fblen = oinfo.fblen;
|
||||
panelinfo->bpp = oinfo.bpp;
|
||||
panelinfo->fbmem = oinfo.fbmem;
|
||||
panelinfo->fblen = oinfo.fblen;
|
||||
panelinfo->fbcount = oinfo.yres_virtual == 0 ?
|
||||
1 : (oinfo.yres_virtual / oinfo.yres);
|
||||
panelinfo->bpp = oinfo.bpp;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@ -954,9 +1126,18 @@ static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
|
||||
return ret;
|
||||
}
|
||||
|
||||
panelinfo->fbmem = pinfo.fbmem;
|
||||
panelinfo->fblen = pinfo.fblen;
|
||||
panelinfo->bpp = pinfo.bpp;
|
||||
ret = fb->vtable->getvideoinfo(fb->vtable, &vinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
gerr("ERROR: getvideoinfo() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
panelinfo->fbmem = pinfo.fbmem;
|
||||
panelinfo->fblen = pinfo.fblen;
|
||||
panelinfo->fbcount = pinfo.yres_virtual == 0 ?
|
||||
1 : (pinfo.yres_virtual / vinfo.yres);
|
||||
panelinfo->bpp = pinfo.bpp;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -994,19 +1175,25 @@ static int fb_get_planeinfo(FAR struct fb_chardev_s *fb,
|
||||
|
||||
static void fb_do_pollnotify(wdparm_t arg)
|
||||
{
|
||||
FAR struct fb_chardev_s *fb = (FAR struct fb_chardev_s *)arg;
|
||||
FAR struct fb_paninfo_s *paninfo = (FAR struct fb_paninfo_s *)arg;
|
||||
irqstate_t flags;
|
||||
int i;
|
||||
|
||||
fb->pollcnt++;
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Notify framebuffer is writable. */
|
||||
for (i = 0; i < CONFIG_VIDEO_FB_NPOLLWAITERS; i++)
|
||||
{
|
||||
if (paninfo->fds[i] != NULL)
|
||||
{
|
||||
/* Notify framebuffer is writable. */
|
||||
|
||||
poll_notify(&fb->fds, 1, POLLOUT);
|
||||
poll_notify(&paninfo->fds[i], 1, POLLOUT);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_pollnotify
|
||||
*
|
||||
@ -1018,9 +1205,10 @@ static void fb_do_pollnotify(wdparm_t arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void fb_pollnotify(FAR struct fb_vtable_s *vtable)
|
||||
static void fb_pollnotify(FAR struct fb_vtable_s *vtable, int overlay)
|
||||
{
|
||||
FAR struct fb_chardev_s *fb;
|
||||
int id = overlay + 1;
|
||||
|
||||
DEBUGASSERT(vtable != NULL);
|
||||
|
||||
@ -1033,16 +1221,170 @@ void fb_pollnotify(FAR struct fb_vtable_s *vtable)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGASSERT(id >= 0 && id < fb->paninfo_count);
|
||||
|
||||
if (fb->vsyncoffset > 0)
|
||||
{
|
||||
wd_start(&fb->wdog, fb->vsyncoffset, fb_do_pollnotify, (wdparm_t)fb);
|
||||
wd_start(&fb->wdog, fb->vsyncoffset, fb_do_pollnotify,
|
||||
(wdparm_t)(&fb->paninfo[id]));
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_do_pollnotify((wdparm_t)fb);
|
||||
fb_do_pollnotify((wdparm_t)(&fb->paninfo[id]));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_peek_paninfo
|
||||
* Description:
|
||||
* Peek a frame from pan info queue of the specified overlay.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* info - Pointer to pan info.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success; a negated errno value is returned on any
|
||||
* failure.
|
||||
****************************************************************************/
|
||||
|
||||
int fb_peek_paninfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR union fb_paninfo_u *info,
|
||||
int overlay)
|
||||
{
|
||||
FAR struct circbuf_s *panbuf;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
irqstate_t flags;
|
||||
ssize_t ret;
|
||||
|
||||
/* Prevent calling before getting the vtable. */
|
||||
|
||||
fb = vtable->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panbuf = fb_get_panbuf(fb, overlay);
|
||||
if (panbuf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Attempt to peek a frame from the vsync queue. */
|
||||
|
||||
ret = circbuf_peek(panbuf, info, sizeof(union fb_paninfo_u));
|
||||
DEBUGASSERT(ret <= 0 || ret == sizeof(union fb_paninfo_u));
|
||||
|
||||
/* Re-enable interrupts */
|
||||
|
||||
leave_critical_section(flags);
|
||||
return ret <= 0 ? -ENOSPC : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_remove_paninfo
|
||||
* Description:
|
||||
* Remove a frame from pan info queue of the specified overlay.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success; a negated errno value is returned on any
|
||||
* failure.
|
||||
****************************************************************************/
|
||||
|
||||
int fb_remove_paninfo(FAR struct fb_vtable_s *vtable, int overlay)
|
||||
{
|
||||
FAR struct circbuf_s *panbuf;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
irqstate_t flags;
|
||||
ssize_t ret;
|
||||
|
||||
fb = vtable->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panbuf = fb_get_panbuf(fb, overlay);
|
||||
if (panbuf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Attempt to take a frame from the pan info. */
|
||||
|
||||
ret = circbuf_skip(panbuf, sizeof(union fb_paninfo_u));
|
||||
DEBUGASSERT(ret <= 0 || ret == sizeof(union fb_paninfo_u));
|
||||
|
||||
/* Re-enable interrupts */
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
if (ret == sizeof(union fb_paninfo_u))
|
||||
{
|
||||
fb_pollnotify(vtable, overlay);
|
||||
}
|
||||
|
||||
return ret <= 0 ? -ENOSPC : OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_paninfo_count
|
||||
* Description:
|
||||
* Get pan info count of specified overlay pan info queue.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* a non-negative value is returned on success; a negated errno value is
|
||||
* returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
int fb_paninfo_count(FAR struct fb_vtable_s *vtable, int overlay)
|
||||
{
|
||||
FAR struct circbuf_s *panbuf;
|
||||
FAR struct fb_chardev_s *fb;
|
||||
irqstate_t flags;
|
||||
ssize_t ret;
|
||||
|
||||
/* Prevent calling before getting the vtable. */
|
||||
|
||||
fb = vtable->priv;
|
||||
if (fb == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panbuf = fb_get_panbuf(fb, overlay);
|
||||
if (panbuf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
ret = circbuf_used(panbuf) / sizeof(union fb_paninfo_u);
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_register
|
||||
*
|
||||
@ -1071,13 +1413,10 @@ int fb_register(int display, int plane)
|
||||
FAR struct fb_chardev_s *fb;
|
||||
struct fb_panelinfo_s panelinfo;
|
||||
struct fb_videoinfo_s vinfo;
|
||||
struct fb_planeinfo_s pinfo;
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
struct fb_overlayinfo_s oinfo;
|
||||
#endif
|
||||
char devname[16];
|
||||
int nplanes;
|
||||
int ret;
|
||||
size_t i;
|
||||
|
||||
/* Allocate a framebuffer state instance */
|
||||
|
||||
@ -1087,13 +1426,6 @@ int fb_register(int display, int plane)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
|
||||
/* Set the default overlay number */
|
||||
|
||||
fb->overlay = FB_NO_OVERLAY;
|
||||
#endif
|
||||
|
||||
/* Initialize the frame buffer device. */
|
||||
|
||||
ret = up_fbinitialize(display);
|
||||
@ -1127,57 +1459,38 @@ int fb_register(int display, int plane)
|
||||
nplanes = vinfo.nplanes;
|
||||
DEBUGASSERT(vinfo.nplanes > 0 && (unsigned)plane < vinfo.nplanes);
|
||||
|
||||
/* Get plane info */
|
||||
|
||||
ret = fb_get_planeinfo(fb, &pinfo, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_fb;
|
||||
}
|
||||
|
||||
/* The initial value of pollcnt is the number of virtual framebuffers */
|
||||
|
||||
if (pinfo.yres_virtual > 0)
|
||||
{
|
||||
fb->pollcnt = pinfo.yres_virtual / vinfo.yres;
|
||||
DEBUGASSERT(fb->pollcnt > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb->pollcnt = 1;
|
||||
}
|
||||
|
||||
/* Get panel info */
|
||||
|
||||
ret = fb_get_panelinfo(fb, &panelinfo);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_fb;
|
||||
}
|
||||
|
||||
/* Clear the framebuffer memory */
|
||||
|
||||
memset(panelinfo.fbmem, 0, panelinfo.fblen);
|
||||
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
/* Initialize first overlay but do not select */
|
||||
fb->paninfo_count = vinfo.noverlays;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(fb->vtable->getoverlayinfo != NULL);
|
||||
memset(&oinfo, 0, sizeof(oinfo));
|
||||
ret = fb->vtable->getoverlayinfo(fb->vtable, 0, &oinfo);
|
||||
if (ret < 0)
|
||||
/* Add the primary framebuffer */
|
||||
|
||||
fb->paninfo_count += 1;
|
||||
fb->paninfo = kmm_zalloc(sizeof(struct fb_paninfo_s) * fb->paninfo_count);
|
||||
|
||||
if (fb->paninfo == NULL)
|
||||
{
|
||||
gerr("ERROR: getoverlayinfo() failed: %d\n", ret);
|
||||
gerr("ERROR: alloc panbuf failed\n");
|
||||
goto errout_with_fb;
|
||||
}
|
||||
|
||||
/* Clear the overlay memory. Necessary when plane 0 and overlay 0
|
||||
* different.
|
||||
*/
|
||||
for (i = 0; i < fb->paninfo_count; i++)
|
||||
{
|
||||
ret = fb_get_panelinfo(fb, &panelinfo, i - 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_paninfo;
|
||||
}
|
||||
|
||||
memset(oinfo.fbmem, 0, oinfo.fblen);
|
||||
#endif
|
||||
ret = circbuf_init(&(fb->paninfo[i].buf), NULL, panelinfo.fbcount
|
||||
* sizeof(union fb_paninfo_u));
|
||||
|
||||
DEBUGASSERT(ret == 0);
|
||||
|
||||
/* Clear the framebuffer memory */
|
||||
|
||||
memset(panelinfo.fbmem, 0, panelinfo.fblen);
|
||||
}
|
||||
|
||||
/* Register the framebuffer device */
|
||||
|
||||
@ -1196,15 +1509,23 @@ int fb_register(int display, int plane)
|
||||
if (ret < 0)
|
||||
{
|
||||
gerr("ERROR: register_driver() failed: %d\n", ret);
|
||||
goto errout_with_fb;
|
||||
goto errout_with_nxmutex;
|
||||
}
|
||||
|
||||
fb->vtable->priv = fb;
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_fb:
|
||||
errout_with_nxmutex:
|
||||
nxmutex_destroy(&fb->lock);
|
||||
errout_with_paninfo:
|
||||
while (i-- > 0)
|
||||
{
|
||||
circbuf_uninit(&(fb->paninfo[i].buf));
|
||||
}
|
||||
|
||||
kmm_free(fb->paninfo);
|
||||
errout_with_fb:
|
||||
kmm_free(fb);
|
||||
return ret;
|
||||
}
|
||||
|
@ -181,6 +181,8 @@
|
||||
|
||||
/* Hardware overlay acceleration ********************************************/
|
||||
|
||||
#define FB_NO_OVERLAY -1
|
||||
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
# define FB_ACCL_TRANSP 0x01 /* Hardware tranparency support */
|
||||
# define FB_ACCL_CHROMA 0x02 /* Hardware chromakey support */
|
||||
@ -673,6 +675,14 @@ struct fb_setcursor_s
|
||||
};
|
||||
#endif
|
||||
|
||||
union fb_paninfo_u
|
||||
{
|
||||
struct fb_planeinfo_s planeinfo;
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
struct fb_overlayinfo_s overlayinfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The framebuffer "object" is accessed through within the OS via
|
||||
* the following vtable:
|
||||
*/
|
||||
@ -996,17 +1006,55 @@ FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane);
|
||||
void up_fbuninitialize(int display);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_pollnotify
|
||||
*
|
||||
* Name: fb_peek_paninfo
|
||||
* Description:
|
||||
* Notify the waiting thread that the framebuffer can be written.
|
||||
* Peek a frame from pan info queue of the specified overlay.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* info - Pointer to pan info.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success; a negated errno value is returned on any
|
||||
* failure.
|
||||
****************************************************************************/
|
||||
|
||||
void fb_pollnotify(FAR struct fb_vtable_s *vtable);
|
||||
int fb_peek_paninfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR union fb_paninfo_u *info,
|
||||
int overlay);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_remove_paninfo
|
||||
* Description:
|
||||
* Remove a frame from pan info queue of the specified overlay.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned on success; a negated errno value is returned on any
|
||||
* failure.
|
||||
****************************************************************************/
|
||||
|
||||
int fb_remove_paninfo(FAR struct fb_vtable_s *vtable, int overlay);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_paninfo_count
|
||||
* Description:
|
||||
* Get pan info count of specified overlay pan info queue.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtable - Pointer to framebuffer's virtual table.
|
||||
* overlay - Overlay index.
|
||||
*
|
||||
* Returned Value:
|
||||
* a non-negative value is returned on success; a negated errno value is
|
||||
* returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
int fb_paninfo_count(FAR struct fb_vtable_s *vtable, int overlay);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_register
|
||||
|
Loading…
Reference in New Issue
Block a user