X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/3bad22d5566624804a73b3791980bab2d84c8266..540206b4c6f2da5a4e1cd12b61587e3e626b27dd:/lib/gdi/fb.cpp diff --git a/lib/gdi/fb.cpp b/lib/gdi/fb.cpp index 4b8a56c9..e5bb46d0 100644 --- a/lib/gdi/fb.cpp +++ b/lib/gdi/fb.cpp @@ -7,9 +7,17 @@ #include #include -#include #include +#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(1); - return; -nolfb: - lfb=0; - printf("framebuffer not available.\n"); return; } @@ -83,18 +79,37 @@ 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.xres_virtual=screeninfo.xres=nxRes; + 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,78 +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); + 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; } @@ -183,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; +} +