mplayer: omapfb: rework doublebuffer handling
authorGrazvydas Ignotas <notasas@gmail.com>
Sat, 26 Nov 2011 20:18:41 +0000 (22:18 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Sat, 26 Nov 2011 20:22:55 +0000 (22:22 +0200)
use tripple buffering when possible so we can avoid waiting until pan
finishes and go on with the next frame. Also allocate appropriate amount
of vram for this automatically.

recipes/mplayer/files/vo_omapfb.c
recipes/mplayer/mplayer_svn.bb

index a3efc23..ef7c61b 100644 (file)
@@ -85,7 +85,7 @@ static vo_info_t info = {
 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;
@@ -95,7 +95,7 @@ static struct fb_var_screeninfo sinfo_p0;
 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;
 
@@ -103,9 +103,9 @@ static struct {
     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);
 
@@ -146,7 +146,7 @@ static void getPrimaryPlaneInfo()
 
     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);
@@ -241,6 +241,7 @@ static int preinit(const char *arg)
     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())
     {
@@ -369,12 +370,26 @@ static void omapfb_update(int x, int y, int out_w, int out_h, int show)
     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;
@@ -428,6 +443,48 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width,
         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");
@@ -437,30 +494,26 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width,
     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) {
@@ -507,19 +560,36 @@ static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
     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;
     }
 }
 
@@ -541,6 +611,7 @@ static void uninit()
 {
     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;
@@ -549,6 +620,8 @@ static void uninit()
         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)
index dd94767..f6efd23 100644 (file)
@@ -39,7 +39,7 @@ RCONFLICTS_${PN} = "mplayer-atty"
 RREPLACES_${PN} = "mplayer-atty"
 
 PV = "0.0+1.0rc3+svnr${SRCPV}"
-PR = "r19"
+PR = "r20"
 DEFAULT_PREFERENCE = "-1"
 DEFAULT_PREFERENCE_angstrom = "1"
 DEFAULT_PREFERENCE_shr = "1"