LIBVO_EXTERN(omapfb)
static int fb_overlay_only = 0; // if set, we need only framebuffer overlay, but do not need any x11 code
-static int dbl_buffer = 0;
+static int dbl_buffer = 1;
static int fullscreen_flag = 0;
static int plane_ready = 0;
static uint32_t drwX, drwY;
static struct fb_var_screeninfo sinfo;
static struct fb_var_screeninfo sinfo2;
static struct fb_fix_screeninfo finfo;
-static struct omapfb_mem_info minfo;
+static struct omapfb_mem_info minfo, minfo_old;
static struct omapfb_plane_info pinfo;
static int xoff, yoff;
unsigned x;
unsigned y;
uint8_t *buf;
-} fb_pages[2];
+} fb_pages[3]; /* 3 pages allow us not to wait for pan */
static int dev_fd = -1;
-static int fb_page_flip = 0;
+static int fb_page_count = 0;
static int page = 0;
static void omapfb_update(int x, int y, int out_w, int out_h, int show);
if (dev_fd == -1) {
mp_msg(MSGT_VO, MSGL_FATAL, "[omapfb] Error /dev/fb0\n");
- return -1;
+ return;
}
ioctl(dev_fd, FBIOGET_VSCREENINFO, &sinfo_p0);
ioctl(dev_fd, FBIOGET_VSCREENINFO, &sinfo);
ioctl(dev_fd, OMAPFB_QUERY_PLANE, &pinfo);
ioctl(dev_fd, OMAPFB_QUERY_MEM, &minfo);
+ memcpy(&minfo_old, &minfo, sizeof(minfo_old));
if (!fb_overlay_only && !vo_init())
{
ioctl(dev_fd, OMAPFB_SETUP_PLANE, &pinfo);
}
+static int realloc_fb_vram(int size)
+{
+ int ret;
+
+ minfo.size = size;
+ ret = ioctl(dev_fd, OMAPFB_SETUP_MEM, &minfo);
+ if (ret == 0)
+ return 0;
+
+ // restore minfo
+ ioctl(dev_fd, OMAPFB_QUERY_MEM, &minfo);
+ return ret;
+}
+
static int config(uint32_t width, uint32_t height, uint32_t d_width,
uint32_t d_height, uint32_t flags, char *title,
uint32_t format)
{
uint8_t *fbmem;
- int i;
+ int i, ret, mem_needed;
struct omapfb_color_key color_key;
XVisualInfo vinfo;
vo_xv_draw_colorkey(drwX, drwY, vo_dwidth - 1, vo_dheight - 1);
}
+ sinfo.xres = width & ~15;
+ sinfo.yres = height & ~15;
+ sinfo.xres_virtual = sinfo.xres;
+ sinfo.yres_virtual = sinfo.yres + 16;
+ sinfo.xoffset = 0;
+ sinfo.yoffset = 0;
+ sinfo.nonstd = OMAPFB_COLOR_YUY422;
+
+ fb_page_count = 1;
+ if (dbl_buffer) {
+ struct omapfb_mem_info minfo_new;
+ memcpy(&minfo_new, &minfo, sizeof(minfo_new));
+ fb_page_count = 3;
+ mem_needed = sinfo.xres_virtual * sinfo.yres_virtual * 2 * 3;
+ if (minfo.size < mem_needed) {
+ ret = realloc_fb_vram(mem_needed);
+ if (ret != 0) {
+ fb_page_count = 2;
+ mem_needed = sinfo.xres_virtual * sinfo.yres_virtual * 2 * 2;
+ if (minfo.size < mem_needed) {
+ ret = realloc_fb_vram(mem_needed);
+ if (ret != 0) {
+ fb_page_count = 1;
+ dbl_buffer = 0;
+ }
+ }
+ }
+ }
+ }
+
+ mem_needed = sinfo.xres_virtual * sinfo.yres_virtual * 2 * fb_page_count;
+ if (minfo.size < mem_needed) {
+ ret = realloc_fb_vram(mem_needed);
+ if (ret != 0) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[omapfb] Not enough vram, needed %d\n", mem_needed);
+ return -1;
+ }
+ }
+
+ mp_msg(MSGT_VO, MSGL_V, "[omapfb] using %d buffers of %dx%d\n",
+ fb_page_count, sinfo.xres, sinfo.yres);
+
fbmem = mmap(NULL, minfo.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);
if (fbmem == MAP_FAILED) {
mp_msg(MSGT_VO, MSGL_FATAL, "[omapfb] Error mmap\n");
for (i = 0; i < minfo.size / 4; i++)
((uint32_t*)fbmem)[i] = 0x80008000;
- sinfo.xres = width & ~15;
- sinfo.yres = height & ~15;
- sinfo.xoffset = 0;
- sinfo.yoffset = 0;
- sinfo.nonstd = OMAPFB_COLOR_YUY422;
-
fb_pages[0].x = 0;
fb_pages[0].y = 0;
fb_pages[0].buf = fbmem;
-
- if (dbl_buffer && minfo.size >= sinfo.xres * sinfo.yres * 2) {
- sinfo.xres_virtual = sinfo.xres;
- sinfo.yres_virtual = sinfo.yres * 2;
+ if (fb_page_count > 1) {
fb_pages[1].x = 0;
- fb_pages[1].y = sinfo.yres;
- fb_pages[1].buf = fbmem + sinfo.xres * sinfo.yres * 2;
- fb_page_flip = 1;
- } else {
- sinfo.xres_virtual = sinfo.xres;
- sinfo.yres_virtual = sinfo.yres;
- fb_page_flip = 0;
+ fb_pages[1].y = sinfo.yres_virtual;
+ fb_pages[1].buf = fbmem + sinfo.xres_virtual * sinfo.yres_virtual * 2;
}
+ if (fb_page_count > 2) {
+ fb_pages[2].x = 0;
+ fb_pages[2].y = sinfo.yres_virtual * 2;
+ fb_pages[2].buf = fbmem + sinfo.xres_virtual * sinfo.yres_virtual * 2 * 2;
+ }
+ sinfo.yres_virtual *= fb_page_count;
- ioctl(dev_fd, FBIOPUT_VSCREENINFO, &sinfo);
+ ret = ioctl(dev_fd, FBIOPUT_VSCREENINFO, &sinfo);
+ if (ret != 0) {
+ mp_msg(MSGT_VO, MSGL_FATAL, "[omapfb] FBIOPUT_VSCREENINFO error\n");
+ return -1;
+ }
ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo);
if (WinID <= 0) {
if (!plane_ready)
return 0;
- ioctl(dev_fd, OMAPFB_SYNC_GFX);
-
- yuv420_to_yuv422(fb_pages[page].buf + y * finfo.line_length, src[0], src[1], src[2], w & ~15, h, stride[0], stride[1], finfo.line_length);
+ yuv420_to_yuv422(fb_pages[page].buf + y * finfo.line_length, src[0], src[1], src[2], w & ~15, h & ~15, stride[0], stride[1], finfo.line_length);
return 0;
}
+#ifndef OMAPFB_WAITFORGO
+#define OMAPFB_WAITFORGO OMAP_IO(60)
+#endif
+
static void flip_page(void)
{
- if (fb_page_flip) {
+ ioctl(dev_fd, OMAPFB_SYNC_GFX);
+
+ if (fb_page_count > 1) {
sinfo.xoffset = fb_pages[page].x + xoff;
sinfo.yoffset = fb_pages[page].y + yoff;
ioctl(dev_fd, FBIOPAN_DISPLAY, &sinfo);
- page ^= fb_page_flip;
+ if (fb_page_count == 2) {
+ // must sync so we don't overwrite currently dispayed buffer
+ int ret = ioctl(dev_fd, OMAPFB_WAITFORGO);
+ if (ret != 0) {
+ static int warned;
+ if (!warned) {
+ mp_msg(MSGT_VO, MSGL_ERR, "[omapfb] OMAPFB_WAITFORGO is broken\n");
+ warned = 1;
+ }
+ }
+ }
+ page++;
+ if (page >= fb_page_count)
+ page = 0;
}
}
{
pinfo.enabled = 0;
ioctl(dev_fd, OMAPFB_SETUP_PLANE, &pinfo);
+ ioctl(dev_fd, OMAPFB_SETUP_MEM, &minfo_old);
if (!fb_overlay_only) {
struct omapfb_color_key color_key;
ioctl(dev_fd, OMAPFB_SET_COLOR_KEY, &color_key);
}
+ munmap(fb_pages[0].buf, minfo.size);
+ fb_pages[0].buf = NULL;
close(dev_fd);
if (!fb_overlay_only)