apps/examples: fb_main need ioctl(FBIOPAN_DISPLAY) to update and adapt to double buffer mode.
Signed-off-by: jianglianfang <jianglianfang@xiaomi.com>
This commit is contained in:
parent
481d4b6e23
commit
72e186f64a
@ -32,6 +32,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include <nuttx/video/fb.h>
|
#include <nuttx/video/fb.h>
|
||||||
#include <nuttx/video/rgbcolors.h>
|
#include <nuttx/video/rgbcolors.h>
|
||||||
@ -55,6 +56,9 @@ struct fb_state_s
|
|||||||
struct fb_overlayinfo_s oinfo;
|
struct fb_overlayinfo_s oinfo;
|
||||||
#endif
|
#endif
|
||||||
FAR void *fbmem;
|
FAR void *fbmem;
|
||||||
|
FAR void *fbmem2;
|
||||||
|
FAR void *act_fbmem;
|
||||||
|
uint32_t mem2_yoffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -87,6 +91,130 @@ static const uint8_t g_rgb8[NCOLORS] =
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* sync_area
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void sync_area(FAR struct fb_state_s *state)
|
||||||
|
{
|
||||||
|
if (state->fbmem2 == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->act_fbmem == state->fbmem)
|
||||||
|
{
|
||||||
|
memcpy(state->fbmem, state->fbmem2,
|
||||||
|
state->vinfo.yres * state->pinfo.stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(state->fbmem2, state->fbmem,
|
||||||
|
state->vinfo.yres * state->pinfo.stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* pan_display
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void pan_display(FAR struct fb_state_s *state)
|
||||||
|
{
|
||||||
|
struct pollfd pfd;
|
||||||
|
int ret;
|
||||||
|
pfd.fd = state->fd;
|
||||||
|
pfd.events = POLLOUT;
|
||||||
|
|
||||||
|
ret = poll(&pfd, 1, 0);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
if (state->fbmem2 == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->act_fbmem == state->fbmem)
|
||||||
|
{
|
||||||
|
state->pinfo.yoffset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->pinfo.yoffset = state->mem2_yoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl(state->fd, FBIOPAN_DISPLAY,
|
||||||
|
(unsigned long)(uintptr_t)&state->pinfo);
|
||||||
|
|
||||||
|
state->act_fbmem = state->act_fbmem == state->fbmem ?
|
||||||
|
state->fbmem2 : state->fbmem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* fb_init_mem2
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int fb_init_mem2(FAR struct fb_state_s *state,
|
||||||
|
FAR struct fb_planeinfo_s *pinfo)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uintptr_t buf_offset;
|
||||||
|
|
||||||
|
pinfo->display = state->pinfo.display + 1;
|
||||||
|
|
||||||
|
ret = ioctl(state->fd, FBIOGET_PLANEINFO,
|
||||||
|
(unsigned long)(uintptr_t)pinfo);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
int errcode = errno;
|
||||||
|
fprintf(stderr, "ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n",
|
||||||
|
errcode);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check bpp */
|
||||||
|
|
||||||
|
if (pinfo->bpp != state->pinfo.bpp)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: fbmem2 is incorrect");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the buffer address offset,
|
||||||
|
* It needs to be divisible by pinfo.stride
|
||||||
|
*/
|
||||||
|
|
||||||
|
buf_offset = pinfo->fbmem - state->fbmem;
|
||||||
|
|
||||||
|
if ((buf_offset % state->pinfo.stride) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: It is detected that buf_offset(%" PRIuPTR ") "
|
||||||
|
"and stride(%d) are not divisible, please ensure "
|
||||||
|
"that the driver handles the address offset by itself.",
|
||||||
|
buf_offset, state->pinfo.stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the address and yoffset of fbmem2 */
|
||||||
|
|
||||||
|
if (buf_offset == 0)
|
||||||
|
{
|
||||||
|
/* Use consecutive fbmem2. */
|
||||||
|
|
||||||
|
state->mem2_yoffset = state->vinfo.yres;
|
||||||
|
state->fbmem2 = pinfo->fbmem + state->mem2_yoffset * pinfo->stride;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use non-consecutive fbmem2. */
|
||||||
|
|
||||||
|
state->mem2_yoffset = buf_offset / state->pinfo.stride;
|
||||||
|
state->fbmem2 = pinfo->fbmem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* draw_rect
|
* draw_rect
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -99,7 +227,7 @@ static void draw_rect32(FAR struct fb_state_s *state,
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
|
row = (FAR uint8_t *)state->act_fbmem + state->pinfo.stride * area->y;
|
||||||
for (y = 0; y < area->h; y++)
|
for (y = 0; y < area->h; y++)
|
||||||
{
|
{
|
||||||
dest = ((FAR uint32_t *)row) + area->x;
|
dest = ((FAR uint32_t *)row) + area->x;
|
||||||
@ -120,7 +248,7 @@ static void draw_rect16(FAR struct fb_state_s *state,
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
|
row = (FAR uint8_t *)state->act_fbmem + state->pinfo.stride * area->y;
|
||||||
for (y = 0; y < area->h; y++)
|
for (y = 0; y < area->h; y++)
|
||||||
{
|
{
|
||||||
dest = ((FAR uint16_t *)row) + area->x;
|
dest = ((FAR uint16_t *)row) + area->x;
|
||||||
@ -141,7 +269,7 @@ static void draw_rect8(FAR struct fb_state_s *state,
|
|||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
|
row = (FAR uint8_t *)state->act_fbmem + state->pinfo.stride * area->y;
|
||||||
for (y = 0; y < area->h; y++)
|
for (y = 0; y < area->h; y++)
|
||||||
{
|
{
|
||||||
dest = row + area->x;
|
dest = row + area->x;
|
||||||
@ -171,7 +299,7 @@ static void draw_rect1(FAR struct fb_state_s *state,
|
|||||||
|
|
||||||
/* Calculate the framebuffer address of the first row to draw on */
|
/* Calculate the framebuffer address of the first row to draw on */
|
||||||
|
|
||||||
row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
|
row = (FAR uint8_t *)state->act_fbmem + state->pinfo.stride * area->y;
|
||||||
|
|
||||||
/* Calculate the position of the first complete (with all bits) byte.
|
/* Calculate the position of the first complete (with all bits) byte.
|
||||||
* Then calculate the last byte with all the bits.
|
* Then calculate the last byte with all the bits.
|
||||||
@ -263,6 +391,10 @@ static void draw_rect(FAR struct fb_state_s *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FB_UPDATE
|
#ifdef CONFIG_FB_UPDATE
|
||||||
|
int yoffset = state->act_fbmem == state->fbmem ?
|
||||||
|
0 : state->mem2_yoffset;
|
||||||
|
area->y += yoffset;
|
||||||
|
|
||||||
ret = ioctl(state->fd, FBIO_UPDATE,
|
ret = ioctl(state->fd, FBIO_UPDATE,
|
||||||
(unsigned long)((uintptr_t)area));
|
(unsigned long)((uintptr_t)area));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -272,6 +404,11 @@ static void draw_rect(FAR struct fb_state_s *state,
|
|||||||
errcode);
|
errcode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (state->pinfo.yres_virtual == (state->vinfo.yres * 2))
|
||||||
|
{
|
||||||
|
pan_display(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -285,6 +422,7 @@ static void draw_rect(FAR struct fb_state_s *state,
|
|||||||
int main(int argc, FAR char *argv[])
|
int main(int argc, FAR char *argv[])
|
||||||
{
|
{
|
||||||
FAR const char *fbdev = g_default_fbdev;
|
FAR const char *fbdev = g_default_fbdev;
|
||||||
|
struct fb_planeinfo_s pinfo;
|
||||||
struct fb_state_s state;
|
struct fb_state_s state;
|
||||||
struct fb_area_s area;
|
struct fb_area_s area;
|
||||||
int nsteps;
|
int nsteps;
|
||||||
@ -440,8 +578,19 @@ int main(int argc, FAR char *argv[])
|
|||||||
|
|
||||||
printf("Mapped FB: %p\n", state.fbmem);
|
printf("Mapped FB: %p\n", state.fbmem);
|
||||||
|
|
||||||
|
/* double buffer mode */
|
||||||
|
|
||||||
|
if (state.pinfo.yres_virtual == (state.vinfo.yres * 2))
|
||||||
|
{
|
||||||
|
if ((ret = fb_init_mem2(&state, &pinfo)) < 0)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw some rectangles */
|
/* Draw some rectangles */
|
||||||
|
|
||||||
|
state.act_fbmem = state.fbmem;
|
||||||
nsteps = 2 * (NCOLORS - 1) + 1;
|
nsteps = 2 * (NCOLORS - 1) + 1;
|
||||||
xstep = state.vinfo.xres / nsteps;
|
xstep = state.vinfo.xres / nsteps;
|
||||||
ystep = state.vinfo.yres / nsteps;
|
ystep = state.vinfo.yres / nsteps;
|
||||||
@ -465,10 +614,19 @@ int main(int argc, FAR char *argv[])
|
|||||||
|
|
||||||
width -= (2 * xstep);
|
width -= (2 * xstep);
|
||||||
height -= (2 * ystep);
|
height -= (2 * ystep);
|
||||||
|
|
||||||
|
/* double buffer mode */
|
||||||
|
|
||||||
|
if (state.pinfo.yres_virtual == (state.vinfo.yres * 2))
|
||||||
|
{
|
||||||
|
sync_area(&state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Test finished\n");
|
printf("Test finished\n");
|
||||||
|
ret = EXIT_SUCCESS;
|
||||||
|
out:
|
||||||
munmap(state.fbmem, state.pinfo.fblen);
|
munmap(state.fbmem, state.pinfo.fblen);
|
||||||
close(state.fd);
|
close(state.fd);
|
||||||
return EXIT_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user