remap lfb on resolution change
[vuplus_dvbapp] / lib / gdi / fb.cpp
index 38ae37d..e5bb46d 100644 (file)
@@ -7,9 +7,17 @@
 #include <memory.h>
 #include <linux/kd.h>
 
-#include <lib/base/econfig.h>
 #include <lib/gdi/fb.h>
 
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
+#ifndef FBIO_BLIT
+#define FBIO_SET_MANUAL_BLIT _IOW('F', 0x21, __u8)
+#define FBIO_BLIT 0x22
+#endif
+
 fbClass *fbClass::instance;
 
 fbClass *fbClass::getInstance()
@@ -19,9 +27,11 @@ fbClass *fbClass::getInstance()
 
 fbClass::fbClass(const char *fb)
 {
+       lfb=0;
+       fb_fix_screeninfo fix;
+       m_manual_blit=-1;
        instance=this;
        locked=0;
-       available=0;
        cmap.start=0;
        cmap.len=256;
        cmap.red=red;
@@ -31,39 +41,25 @@ fbClass::fbClass(const char *fb)
 
        fd=open(fb, O_RDWR);
        if (fd<0)
-       {
                perror(fb);
-               goto nolfb;
-       }
-       if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo)<0)
-       {
+       else if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo)<0)
                perror("FBIOGET_VSCREENINFO");
-               goto nolfb;
-       }
-       
-       memcpy(&oldscreen, &screeninfo, sizeof(screeninfo));
-
-       fb_fix_screeninfo fix;
-       if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
-       {
+       else if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
                perror("FBIOGET_FSCREENINFO");
-               goto nolfb;
-       }
-
-       available=fix.smem_len;
-       eDebug("%dk video mem", available/1024);
-       lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
-       if (!lfb)
+       else
        {
-               perror("mmap");
-               goto nolfb;
+               memcpy(&oldscreen, &screeninfo, sizeof(screeninfo));
+               available=fix.smem_len;
+               lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
+               if (!lfb)
+                       perror("mmap");
+               else
+               {
+                       showConsole(0);
+                       enableManualBlit();
+                       stride=fix.line_length;
+               }
        }
-
-//     showConsole(0);
-       return;
-nolfb:
-       lfb=0;
-       printf("framebuffer not available.\n");
        return;
 }
 
@@ -84,17 +80,36 @@ int fbClass::showConsole(int state)
 int fbClass::SetMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp)
 {
        screeninfo.xres_virtual=screeninfo.xres=nxRes;
-       screeninfo.yres_virtual=screeninfo.yres=nyRes;
+       screeninfo.yres_virtual=(screeninfo.yres=nyRes)*2;
        screeninfo.height=0;
        screeninfo.width=0;
        screeninfo.xoffset=screeninfo.yoffset=0;
        screeninfo.bits_per_pixel=nbpp;
+
+       if (lfb) {
+               munmap(lfb, available);
+               lfb = 0;
+       }
+
        if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
        {
-               perror("FBIOPUT_VSCREENINFO");
-               printf("fb failed\n");
-               return -1;
-       }
+               // try single buffering
+               screeninfo.yres_virtual=screeninfo.yres=nyRes;
+               
+               if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
+               {
+                       perror("FBIOPUT_VSCREENINFO");
+                       printf("fb failed\n");
+                       return -1;
+               }
+               eDebug(" - double buffering not available.");
+       } else
+               eDebug(" - double buffering available!");
+       
+       m_number_of_pages = screeninfo.yres_virtual / nyRes;
+       
+       ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
+       
        if ((screeninfo.xres!=nxRes) && (screeninfo.yres!=nyRes) && (screeninfo.bits_per_pixel!=nbpp))
        {
                eDebug("SetMode failed: wanted: %dx%dx%d, got %dx%dx%d",
@@ -104,79 +119,80 @@ int fbClass::SetMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp)
        xRes=screeninfo.xres;
        yRes=screeninfo.yres;
        bpp=screeninfo.bits_per_pixel;
+
        fb_fix_screeninfo fix;
        if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
        {
                perror("FBIOGET_FSCREENINFO");
                printf("fb failed\n");
+               goto nolfb;
+       }
+
+       available=fix.smem_len;
+       eDebug("%dk video mem", available/1024);
+       lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
+       if (!lfb)
+       {
+               perror("mmap");
+               goto nolfb;
        }
+
        stride=fix.line_length;
-       memset(lfb, 0, stride*yRes);
+
        return 0;
+nolfb:
+       lfb=0;
+       eFatal("framebuffer no more ready after SetMode(%d, %d, %d)", nxRes, nyRes, nbpp);
+       return -1;
 }
 
-fbClass::~fbClass()
+int fbClass::setOffset(int off)
 {
-       if (available)
-               ioctl(fd, FBIOPUT_VSCREENINFO, &oldscreen);
-       if (lfb)
-               munmap(lfb, available);
-       showConsole(1);
+       screeninfo.xoffset = 0;
+       screeninfo.yoffset = off;
+       return ioctl(fd, FBIOPAN_DISPLAY, &screeninfo);
 }
 
-int fbClass::PutCMAP()
+int fbClass::waitVSync()
 {
-       return ioctl(fd, FBIOPUTCMAP, &cmap);
+       int c = 0;
+       return ioctl(fd, FBIO_WAITFORVSYNC, &c);
 }
 
-void fbClass::Box(int x, int y, int width, int height, int color, int backcolor)
+void fbClass::blit()
 {
-       if (width<=2 || locked)
-               return;
-       int offset=y*stride+x/2;
-       int first=0xF0|((color&0xF0)>>4);
-       int last= 0xF0|((backcolor&0xF0)>>4);
-       color=(color&0xF)*0x11;
-       int halfwidth=width/2;
-       for (int ay=y; ay<(y+height); ay++)
-       {
-               lfb[offset]=first;
-               memset(lfb+offset+1, color, halfwidth-2);
-               lfb[offset+halfwidth-1]=last;
-               offset+=stride;
+       if (m_manual_blit == 1) {
+               if (ioctl(fd, FBIO_BLIT) < 0)
+                       perror("FBIO_BLIT");
        }
 }
 
-void fbClass::NBox(int x, int y, int width, int height, int color)
+fbClass::~fbClass()
 {
-       if (locked)
-               return;
-       int offset=y*stride+x/2;
-       int halfwidth=width/2;
-       for (int ay=y; ay<(y+height); ay++)
-       {
-               memset(lfb+offset, color, halfwidth);
-               offset+=stride;
-       }
+       if (available)
+               ioctl(fd, FBIOPUT_VSCREENINFO, &oldscreen);
+       if (lfb)
+               munmap(lfb, available);
+       showConsole(1);
+       disableManualBlit();
 }
 
-void fbClass::VLine(int x, int y, int sy, int color)
+int fbClass::PutCMAP()
 {
-       if (locked)
-               return;
-       int offset=y*stride+x/2;
-       while (sy--)
-       {
-               lfb[offset]=color;
-               offset+=stride;
-       }
+       return ioctl(fd, FBIOPUTCMAP, &cmap);
 }
 
 int fbClass::lock()
 {
        if (locked)
                return -1;
-       locked=1;
+       if (m_manual_blit == 1)
+       {
+               locked = 2;
+               disableManualBlit();
+       }
+       else
+               locked = 1;
        return fd;
 }
 
@@ -184,7 +200,28 @@ void fbClass::unlock()
 {
        if (!locked)
                return;
+       if (locked == 2)  // re-enable manualBlit
+               enableManualBlit();
        locked=0;
        SetMode(xRes, yRes, bpp);
        PutCMAP();
 }
+
+void fbClass::enableManualBlit()
+{
+       unsigned char tmp = 1;
+       if (ioctl(fd,FBIO_SET_MANUAL_BLIT, &tmp)<0)
+               perror("FBIO_SET_MANUAL_BLIT");
+       else
+               m_manual_blit = 1;
+}
+
+void fbClass::disableManualBlit()
+{
+       unsigned char tmp = 0;
+       if (ioctl(fd,FBIO_SET_MANUAL_BLIT, &tmp)<0) 
+               perror("FBIO_SET_MANUAL_BLIT");
+       else
+               m_manual_blit = 0;
+}
+