adf06a2c12ea2033ad640f46de06dccab30c6f3f
[enigma2.git] / lib / gdi / fb.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <sys/ioctl.h>
5 #include <unistd.h>
6 #include <sys/mman.h>
7 #include <memory.h>
8 #include <linux/kd.h>
9
10 #include <lib/gdi/fb.h>
11
12 #ifndef FBIO_WAITFORVSYNC
13 #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
14 #endif
15
16 #ifndef FBIO_BLIT
17 #define FBIO_SET_MANUAL_BLIT _IOW('F', 0x21, __u8)
18 #define FBIO_BLIT 0x22
19 #endif
20
21 fbClass *fbClass::instance;
22
23 fbClass *fbClass::getInstance()
24 {
25         return instance;
26 }
27
28 fbClass::fbClass(const char *fb)
29 {
30         m_manual_blit=0;
31         instance=this;
32         locked=0;
33         available=0;
34         cmap.start=0;
35         cmap.len=256;
36         cmap.red=red;
37         cmap.green=green;
38         cmap.blue=blue;
39         cmap.transp=trans;
40
41         fd=open(fb, O_RDWR);
42         if (fd<0)
43         {
44                 perror(fb);
45                 goto nolfb;
46         }
47
48
49         if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo)<0)
50         {
51                 perror("FBIOGET_VSCREENINFO");
52                 goto nolfb;
53         }
54         
55         memcpy(&oldscreen, &screeninfo, sizeof(screeninfo));
56
57         fb_fix_screeninfo fix;
58         if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
59         {
60                 perror("FBIOGET_FSCREENINFO");
61                 goto nolfb;
62         }
63
64         available=fix.smem_len;
65         eDebug("%dk video mem", available/1024);
66         lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
67         if (!lfb)
68         {
69                 perror("mmap");
70                 goto nolfb;
71         }
72
73         showConsole(0);
74
75         enableManualBlit();
76         return;
77 nolfb:
78         lfb=0;
79         printf("framebuffer not available.\n");
80         return;
81 }
82
83 int fbClass::showConsole(int state)
84 {
85         int fd=open("/dev/vc/0", O_RDWR);
86         if(fd>=0)
87         {
88                 if(ioctl(fd, KDSETMODE, state?KD_TEXT:KD_GRAPHICS)<0)
89                 {
90                         eDebug("setting /dev/vc/0 status failed.");
91                 }
92                 close(fd);
93         }
94         return 0;
95 }
96
97 int fbClass::SetMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp)
98 {
99         screeninfo.xres_virtual=screeninfo.xres=nxRes;
100         screeninfo.yres_virtual=(screeninfo.yres=nyRes)*2;
101         screeninfo.height=0;
102         screeninfo.width=0;
103         screeninfo.xoffset=screeninfo.yoffset=0;
104         screeninfo.bits_per_pixel=nbpp;
105         
106         if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
107         {
108                 // try single buffering
109                 screeninfo.yres_virtual=screeninfo.yres=nyRes;
110                 
111                 if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
112                 {
113                         perror("FBIOPUT_VSCREENINFO");
114                         printf("fb failed\n");
115                         return -1;
116                 }
117                 eDebug(" - double buffering not available.");
118         } else
119                 eDebug(" - double buffering available!");
120         
121         m_number_of_pages = screeninfo.yres_virtual / nyRes;
122         
123         ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
124         
125         if ((screeninfo.xres!=nxRes) && (screeninfo.yres!=nyRes) && (screeninfo.bits_per_pixel!=nbpp))
126         {
127                 eDebug("SetMode failed: wanted: %dx%dx%d, got %dx%dx%d",
128                         nxRes, nyRes, nbpp,
129                         screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel);
130         }
131         xRes=screeninfo.xres;
132         yRes=screeninfo.yres;
133         bpp=screeninfo.bits_per_pixel;
134         fb_fix_screeninfo fix;
135         if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
136         {
137                 perror("FBIOGET_FSCREENINFO");
138                 printf("fb failed\n");
139         }
140         stride=fix.line_length;
141         memset(lfb, 0, stride*yRes);
142         return 0;
143 }
144
145 int fbClass::setOffset(int off)
146 {
147         screeninfo.xoffset = 0;
148         screeninfo.yoffset = off;
149         return ioctl(fd, FBIOPAN_DISPLAY, &screeninfo);
150 }
151
152 int fbClass::waitVSync()
153 {
154         int c = 0;
155         return ioctl(fd, FBIO_WAITFORVSYNC, &c);
156 }
157
158 void fbClass::blit()
159 {
160         if (m_manual_blit) {
161                 if (ioctl(fd, FBIO_BLIT) < 0)
162                         perror("FBIO_BLIT");
163         }
164 }
165
166 fbClass::~fbClass()
167 {
168         if (available)
169                 ioctl(fd, FBIOPUT_VSCREENINFO, &oldscreen);
170         if (lfb)
171                 munmap(lfb, available);
172         showConsole(1);
173         disableManualBlit();
174 }
175
176 int fbClass::PutCMAP()
177 {
178         return ioctl(fd, FBIOPUTCMAP, &cmap);
179 }
180
181 int fbClass::lock()
182 {
183         if (locked)
184                 return -1;
185         locked=1;
186         return fd;
187 }
188
189 void fbClass::unlock()
190 {
191         if (!locked)
192                 return;
193         locked=0;
194         SetMode(xRes, yRes, bpp);
195         PutCMAP();
196 }
197
198 void fbClass::enableManualBlit()
199 {
200         unsigned char tmp = 1;
201         if (ioctl(fd,FBIO_SET_MANUAL_BLIT, &tmp)<0)
202                 perror("FBIO_SET_MANUAL_BLIT");
203         else
204                 m_manual_blit = 1;
205 }
206
207 void fbClass::disableManualBlit()
208 {
209         unsigned char tmp = 0;
210         if (ioctl(fd,FBIO_SET_MANUAL_BLIT, &tmp)<0) 
211                 perror("FBIO_SET_MANUAL_BLIT");
212         else
213                 m_manual_blit = 0;
214 }
215