Extrenal srt problem gst-1 solved.
[openblackhole/openblackhole-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, uint32_t)
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=-1;
31         instance=this;
32         locked=0;
33         lfb = 0;
34         available=0;
35         cmap.start=0;
36         cmap.len=256;
37         cmap.red=red;
38         cmap.green=green;
39         cmap.blue=blue;
40         cmap.transp=trans;
41
42         fbFd=open(fb, O_RDWR);
43         if (fbFd<0)
44         {
45                 eDebug("[fb] %s %m", fb);
46                 goto nolfb;
47         }
48
49
50         if (ioctl(fbFd, FBIOGET_VSCREENINFO, &screeninfo)<0)
51         {
52                 eDebug("[fb] FBIOGET_VSCREENINFO: %m");
53                 goto nolfb;
54         }
55
56         fb_fix_screeninfo fix;
57         if (ioctl(fbFd, FBIOGET_FSCREENINFO, &fix)<0)
58         {
59                 eDebug("[fb] FBIOGET_FSCREENINFO: %m");
60                 goto nolfb;
61         }
62
63         available=fix.smem_len;
64         m_phys_mem = fix.smem_start;
65         eDebug("[fb] %dk video mem", available/1024);
66         lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fbFd, 0);
67         if (!lfb)
68         {
69                 eDebug("[fb] mmap: %m");
70                 goto nolfb;
71         }
72
73         showConsole(0);
74
75         enableManualBlit();
76         return;
77 nolfb:
78         if (fbFd >= 0)
79         {
80                 ::close(fbFd);
81                 fbFd = -1;
82         }
83         eDebug("[fb] framebuffer not available");
84         return;
85 }
86
87 int fbClass::showConsole(int state)
88 {
89         int fd=open("/dev/tty0", O_RDWR);
90         if(fd>=0)
91         {
92                 if(ioctl(fd, KDSETMODE, state?KD_TEXT:KD_GRAPHICS)<0)
93                 {
94                         eDebug("[fb] setting /dev/tty0 status failed.");
95                 }
96                 close(fd);
97         }
98         return 0;
99 }
100
101 int fbClass::SetMode(int nxRes, int nyRes, int nbpp)
102 {
103         if (fbFd < 0) return -1;
104         screeninfo.xres_virtual=screeninfo.xres=nxRes;
105         screeninfo.yres_virtual=(screeninfo.yres=nyRes)*2;
106         screeninfo.height=0;
107         screeninfo.width=0;
108         screeninfo.xoffset=screeninfo.yoffset=0;
109         screeninfo.bits_per_pixel=nbpp;
110
111         switch (nbpp) {
112         case 16:
113                 // ARGB 1555
114                 screeninfo.transp.offset = 15;
115                 screeninfo.transp.length = 1;
116                 screeninfo.red.offset = 10;
117                 screeninfo.red.length = 5;
118                 screeninfo.green.offset = 5;
119                 screeninfo.green.length = 5;
120                 screeninfo.blue.offset = 0;
121                 screeninfo.blue.length = 5;
122                 break;
123         case 32:
124                 // ARGB 8888
125                 screeninfo.transp.offset = 24;
126                 screeninfo.transp.length = 8;
127                 screeninfo.red.offset = 16;
128                 screeninfo.red.length = 8;
129                 screeninfo.green.offset = 8;
130                 screeninfo.green.length = 8;
131                 screeninfo.blue.offset = 0;
132                 screeninfo.blue.length = 8;
133                 break;
134         }
135
136         if (ioctl(fbFd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
137         {
138                 // try single buffering
139                 screeninfo.yres_virtual=screeninfo.yres=nyRes;
140
141                 if (ioctl(fbFd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
142                 {
143                         eDebug("[fb] FBIOPUT_VSCREENINFO: %m");
144                         return -1;
145                 }
146                 eDebug("[fb] double buffering not available.");
147         } else
148                 eDebug("[fb] double buffering available!");
149
150         m_number_of_pages = screeninfo.yres_virtual / nyRes;
151
152         ioctl(fbFd, FBIOGET_VSCREENINFO, &screeninfo);
153
154         if ((screeninfo.xres!=nxRes) && (screeninfo.yres!=nyRes) && (screeninfo.bits_per_pixel!=nbpp))
155         {
156                 eDebug("[fb] SetMode failed: wanted: %dx%dx%d, got %dx%dx%d",
157                         nxRes, nyRes, nbpp,
158                         screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel);
159         }
160         xRes=screeninfo.xres;
161         yRes=screeninfo.yres;
162         bpp=screeninfo.bits_per_pixel;
163         fb_fix_screeninfo fix;
164         if (ioctl(fbFd, FBIOGET_FSCREENINFO, &fix)<0)
165         {
166                 eDebug("[fb] FBIOGET_FSCREENINFO: %m");
167         }
168         stride=fix.line_length;
169         memset(lfb, 0, stride*yRes);
170         blit();
171         return 0;
172 }
173
174 void fbClass::getMode(int &xres, int &yres, int &bpp)
175 {
176         xres = screeninfo.xres;
177         yres = screeninfo.yres;
178         bpp = screeninfo.bits_per_pixel;
179 }
180
181 int fbClass::setOffset(int off)
182 {
183         if (fbFd < 0) return -1;
184         screeninfo.xoffset = 0;
185         screeninfo.yoffset = off;
186         return ioctl(fbFd, FBIOPAN_DISPLAY, &screeninfo);
187 }
188
189 int fbClass::waitVSync()
190 {
191         int c = 0;
192         if (fbFd < 0) return -1;
193         return ioctl(fbFd, FBIO_WAITFORVSYNC, &c);
194 }
195
196 void fbClass::blit()
197 {
198         if (fbFd < 0) return;
199         if (m_manual_blit == 1) {
200                 if (ioctl(fbFd, FBIO_BLIT) < 0)
201                         eDebug("[fb] FBIO_BLIT: %m");
202         }
203 }
204
205 fbClass::~fbClass()
206 {
207         if (lfb)
208         {
209                 msync(lfb, available, MS_SYNC);
210                 munmap(lfb, available);
211         }
212         showConsole(1);
213         disableManualBlit();
214         if (fbFd >= 0)
215         {
216                 ::close(fbFd);
217                 fbFd = -1;
218         }
219 }
220
221 int fbClass::PutCMAP()
222 {
223         if (fbFd < 0) return -1;
224         return ioctl(fbFd, FBIOPUTCMAP, &cmap);
225 }
226
227 int fbClass::lock()
228 {
229         if (locked)
230                 return -1;
231         if (m_manual_blit == 1)
232         {
233                 locked = 2;
234                 disableManualBlit();
235         }
236         else
237                 locked = 1;
238         return fbFd;
239 }
240
241 void fbClass::unlock()
242 {
243         if (!locked)
244                 return;
245         if (locked == 2)  // re-enable manualBlit
246                 enableManualBlit();
247         locked=0;
248         SetMode(xRes, yRes, bpp);
249         PutCMAP();
250 }
251
252 void fbClass::enableManualBlit()
253 {
254         unsigned char tmp = 1;
255         if (fbFd < 0) return;
256         if (ioctl(fbFd,FBIO_SET_MANUAL_BLIT, &tmp)<0)
257                 eDebug("[fb] enable FBIO_SET_MANUAL_BLIT: %m");
258         else
259                 m_manual_blit = 1;
260 }
261
262 void fbClass::disableManualBlit()
263 {
264         unsigned char tmp = 0;
265         if (fbFd < 0) return;
266         if (ioctl(fbFd,FBIO_SET_MANUAL_BLIT, &tmp)<0)
267                 eDebug("[fb] disable FBIO_SET_MANUAL_BLIT: %m");
268         else
269                 m_manual_blit = 0;
270 }
271