You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/09/12 14:10:20 UTC
[nuttx] 04/06: video/fb: add vsync queue
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit e578f3b20d4361ad5ebeebc38a746c3860a4ab01
Author: pengyiqiang <pe...@xiaomi.com>
AuthorDate: Wed Jul 19 21:11:07 2023 +0800
video/fb: add vsync queue
refact vsync queue to support multi fb poll and overlay poll.
Signed-off-by: pengyiqiang <pe...@xiaomi.com>
Signed-off-by: rongyichang <ro...@xiaomi.com>
---
drivers/video/Kconfig | 5 +
drivers/video/fb.c | 565 +++++++++++++++++++++++++++++++++++++----------
include/nuttx/video/fb.h | 56 ++++-
3 files changed, 500 insertions(+), 126 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9e97620ea9..4db3f10124 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -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
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index 532522931c..97515eb00b 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -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);
- DEBUGASSERT(pinfo != NULL && fb->vtable != NULL &&
- fb->vtable->pandisplay != NULL);
- ret = fb->vtable->pandisplay(fb->vtable, pinfo);
- fb->pollcnt--;
+ memcpy(&paninfo, pinfo, sizeof(*pinfo));
- /* Check pan display overrun. */
+ if (fb->vtable->pandisplay != NULL)
+ {
+ fb->vtable->pandisplay(fb->vtable, pinfo);
+ }
- DEBUGASSERT(fb->pollcnt >= 0);
+ 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)
- {
- fb->fds = fds;
- fds->priv = &fb->fds;
- }
- else
+ pollfds = fb_get_free_pollfds(fb, priv->overlay);
+ if (pollfds == NULL)
{
- 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,18 +1175,24 @@ 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);
+ }
+ }
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+ leave_critical_section(flags);
+}
/****************************************************************************
* 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,58 +1459,39 @@ int fb_register(int display, int plane)
nplanes = vinfo.nplanes;
DEBUGASSERT(vinfo.nplanes > 0 && (unsigned)plane < vinfo.nplanes);
- /* Get plane info */
+#ifdef CONFIG_FB_OVERLAY
+ fb->paninfo_count = vinfo.noverlays;
+#endif
- ret = fb_get_planeinfo(fb, &pinfo, 0);
- if (ret < 0)
- {
- goto errout_with_fb;
- }
+ /* Add the primary framebuffer */
- /* The initial value of pollcnt is the number of virtual framebuffers */
+ fb->paninfo_count += 1;
+ fb->paninfo = kmm_zalloc(sizeof(struct fb_paninfo_s) * fb->paninfo_count);
- if (pinfo.yres_virtual > 0)
+ if (fb->paninfo == NULL)
{
- fb->pollcnt = pinfo.yres_virtual / vinfo.yres;
- DEBUGASSERT(fb->pollcnt > 0);
- }
- else
- {
- fb->pollcnt = 1;
+ gerr("ERROR: alloc panbuf failed\n");
+ goto errout_with_fb;
}
- /* Get panel info */
-
- ret = fb_get_panelinfo(fb, &panelinfo);
-
- if (ret < 0)
+ for (i = 0; i < fb->paninfo_count; i++)
{
- goto errout_with_fb;
- }
+ ret = fb_get_panelinfo(fb, &panelinfo, i - 1);
+ if (ret < 0)
+ {
+ goto errout_with_paninfo;
+ }
- /* Clear the framebuffer memory */
+ ret = circbuf_init(&(fb->paninfo[i].buf), NULL, panelinfo.fbcount
+ * sizeof(union fb_paninfo_u));
- memset(panelinfo.fbmem, 0, panelinfo.fblen);
+ DEBUGASSERT(ret == 0);
-#ifdef CONFIG_FB_OVERLAY
- /* Initialize first overlay but do not select */
+ /* Clear the framebuffer memory */
- DEBUGASSERT(fb->vtable->getoverlayinfo != NULL);
- memset(&oinfo, 0, sizeof(oinfo));
- ret = fb->vtable->getoverlayinfo(fb->vtable, 0, &oinfo);
- if (ret < 0)
- {
- gerr("ERROR: getoverlayinfo() failed: %d\n", ret);
- goto errout_with_fb;
+ memset(panelinfo.fbmem, 0, panelinfo.fblen);
}
- /* Clear the overlay memory. Necessary when plane 0 and overlay 0
- * different.
- */
-
- memset(oinfo.fbmem, 0, oinfo.fblen);
-#endif
-
/* Register the framebuffer device */
if (nplanes < 2)
@@ -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;
}
diff --git a/include/nuttx/video/fb.h b/include/nuttx/video/fb.h
index 9c69e45182..f597f502e6 100644
--- a/include/nuttx/video/fb.h
+++ b/include/nuttx/video/fb.h
@@ -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:
+ * 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);
+
+/****************************************************************************
+ * 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:
- * Notify the waiting thread that the framebuffer can be written.
+ * Get pan info count of specified overlay pan info queue.
*
* Input Parameters:
- * vtable - Pointer to framebuffer's virtual table.
+ * 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.
****************************************************************************/
-void fb_pollnotify(FAR struct fb_vtable_s *vtable);
+int fb_paninfo_count(FAR struct fb_vtable_s *vtable, int overlay);
/****************************************************************************
* Name: fb_register