- fixed console input mode restore
[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/base/econfig.h>
11 #include <lib/gdi/fb.h>
12
13 fbClass *fbClass::instance;
14
15 fbClass *fbClass::getInstance()
16 {
17         return instance;
18 }
19
20 fbClass::fbClass(const char *fb)
21 {
22         instance=this;
23         locked=0;
24         available=0;
25         cmap.start=0;
26         cmap.len=256;
27         cmap.red=red;
28         cmap.green=green;
29         cmap.blue=blue;
30         cmap.transp=trans;
31
32         fd=open(fb, O_RDWR);
33         if (fd<0)
34         {
35                 perror(fb);
36                 goto nolfb;
37         }
38         if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo)<0)
39         {
40                 perror("FBIOGET_VSCREENINFO");
41                 goto nolfb;
42         }
43         
44         memcpy(&oldscreen, &screeninfo, sizeof(screeninfo));
45
46         fb_fix_screeninfo fix;
47         if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
48         {
49                 perror("FBIOGET_FSCREENINFO");
50                 goto nolfb;
51         }
52
53         available=fix.smem_len;
54         eDebug("%dk video mem", available/1024);
55         lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
56         if (!lfb)
57         {
58                 perror("mmap");
59                 goto nolfb;
60         }
61
62 //      showConsole(0);
63         return;
64 nolfb:
65         lfb=0;
66         printf("framebuffer not available.\n");
67         return;
68 }
69
70 int fbClass::showConsole(int state)
71 {
72         int fd=open("/dev/vc/0", O_RDWR);
73         if(fd>=0)
74         {
75                 if(ioctl(fd, KDSETMODE, state?KD_TEXT:KD_GRAPHICS)<0)
76                 {
77                         eDebug("setting /dev/vc/0 status failed.");
78                 }
79                 close(fd);
80         }
81         return 0;
82 }
83
84 int fbClass::SetMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp)
85 {
86 /*      screeninfo.xres_virtual=screeninfo.xres=nxRes;
87         screeninfo.yres_virtual=screeninfo.yres=nyRes; */
88         screeninfo.height=0;
89         screeninfo.width=0;
90         screeninfo.xoffset=screeninfo.yoffset=0;
91         screeninfo.bits_per_pixel=nbpp;
92         if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0)
93         {
94                 perror("FBIOPUT_VSCREENINFO");
95                 printf("fb failed\n");
96                 return -1;
97         }
98         if ((screeninfo.xres!=nxRes) && (screeninfo.yres!=nyRes) && (screeninfo.bits_per_pixel!=nbpp))
99         {
100                 eDebug("SetMode failed: wanted: %dx%dx%d, got %dx%dx%d",
101                         nxRes, nyRes, nbpp,
102                         screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel);
103         }
104         xRes=screeninfo.xres;
105         yRes=screeninfo.yres;
106         bpp=screeninfo.bits_per_pixel;
107         fb_fix_screeninfo fix;
108         if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
109         {
110                 perror("FBIOGET_FSCREENINFO");
111                 printf("fb failed\n");
112         }
113         stride=fix.line_length;
114         memset(lfb, 0, stride*yRes);
115         return 0;
116 }
117
118 fbClass::~fbClass()
119 {
120         if (available)
121                 ioctl(fd, FBIOPUT_VSCREENINFO, &oldscreen);
122         if (lfb)
123                 munmap(lfb, available);
124         showConsole(1);
125 }
126
127 int fbClass::PutCMAP()
128 {
129         return ioctl(fd, FBIOPUTCMAP, &cmap);
130 }
131
132 void fbClass::Box(int x, int y, int width, int height, int color, int backcolor)
133 {
134         if (width<=2 || locked)
135                 return;
136         int offset=y*stride+x/2;
137         int first=0xF0|((color&0xF0)>>4);
138         int last= 0xF0|((backcolor&0xF0)>>4);
139         color=(color&0xF)*0x11;
140         int halfwidth=width/2;
141         for (int ay=y; ay<(y+height); ay++)
142         {
143                 lfb[offset]=first;
144                 memset(lfb+offset+1, color, halfwidth-2);
145                 lfb[offset+halfwidth-1]=last;
146                 offset+=stride;
147         }
148 }
149
150 void fbClass::NBox(int x, int y, int width, int height, int color)
151 {
152         if (locked)
153                 return;
154         int offset=y*stride+x/2;
155         int halfwidth=width/2;
156         for (int ay=y; ay<(y+height); ay++)
157         {
158                 memset(lfb+offset, color, halfwidth);
159                 offset+=stride;
160         }
161 }
162
163 void fbClass::VLine(int x, int y, int sy, int color)
164 {
165         if (locked)
166                 return;
167         int offset=y*stride+x/2;
168         while (sy--)
169         {
170                 lfb[offset]=color;
171                 offset+=stride;
172         }
173 }
174
175 int fbClass::lock()
176 {
177         if (locked)
178                 return -1;
179         locked=1;
180         return fd;
181 }
182
183 void fbClass::unlock()
184 {
185         if (!locked)
186                 return;
187         locked=0;
188         SetMode(xRes, yRes, bpp);
189         PutCMAP();
190 }