02ebc4ff02134c1898d1b187124424bf4e6039f4
[enigma2.git] / lib / gdi / gfbdc.cpp
1 #include <lib/gdi/gfbdc.h>
2
3 #include <lib/base/init.h>
4 #include <lib/base/init_num.h>
5
6 #include <lib/gdi/accel.h>
7
8 #include <time.h>
9
10 gFBDC *gFBDC::instance;
11
12 gFBDC::gFBDC()
13 {
14         instance=this;
15         fb=new fbClass;
16
17         if (!fb->Available())
18                 eFatal("no framebuffer available");
19
20         surface.clut.data = 0;
21         setResolution(720, 576); // default res
22
23         reloadSettings();
24 }
25
26 gFBDC::~gFBDC()
27 {
28         delete fb;
29         delete[] surface.clut.data;
30         instance=0;
31 }
32
33 void gFBDC::calcRamp()
34 {
35 #if 0
36         float fgamma=gamma ? gamma : 1;
37         fgamma/=10.0;
38         fgamma=1/log(fgamma);
39         for (int i=0; i<256; i++)
40         {
41                 float raw=i/255.0; // IIH, float.
42                 float corr=pow(raw, fgamma) * 256.0;
43
44                 int d=corr * (float)(256-brightness) / 256 + brightness;
45                 if (d < 0)
46                         d=0;
47                 if (d > 255)
48                         d=255;
49                 ramp[i]=d;
50
51                 rampalpha[i]=i*alpha/256;
52         }
53 #endif
54         for (int i=0; i<256; i++)
55         {
56                 int d;
57                 d=i;
58                 d=(d-128)*(gamma+64)/(128+64)+128;
59                 d+=brightness-128; // brightness correction
60                 if (d<0)
61                         d=0;
62                 if (d>255)
63                         d=255;
64                 ramp[i]=d;
65
66                 rampalpha[i]=i*alpha/256;
67         }
68
69         rampalpha[255]=255; // transparent BLEIBT bitte so.
70 }
71
72 void gFBDC::setPalette()
73 {
74         if (!surface.clut.data)
75                 return;
76
77         for (int i=0; i<256; ++i)
78         {
79                 fb->CMAP()->red[i]=ramp[surface.clut.data[i].r]<<8;
80                 fb->CMAP()->green[i]=ramp[surface.clut.data[i].g]<<8;
81                 fb->CMAP()->blue[i]=ramp[surface.clut.data[i].b]<<8;
82                 fb->CMAP()->transp[i]=rampalpha[surface.clut.data[i].a]<<8;
83         }
84         fb->PutCMAP();
85 }
86
87 void gFBDC::exec(gOpcode *o)
88 {
89         switch (o->opcode)
90         {
91         case gOpcode::setPalette:
92         {
93                 gDC::exec(o);
94                 setPalette();
95                 break;
96         }
97         case gOpcode::flip:
98         {
99                 if (m_enable_double_buffering)
100                 {
101                         gSurface s(surface);
102                         surface = surface_back;
103                         surface_back = s;
104
105                         fb->setOffset(surface_back.offset);
106                 }
107                 break;
108         }
109         case gOpcode::waitVSync:
110         {
111                 static timeval l;
112                 static int t;
113                 timeval now;
114
115                 if (t == 1000)
116                 {
117                         gettimeofday(&now, 0);
118
119                         int diff = (now.tv_sec - l.tv_sec) * 1000 + (now.tv_usec - l.tv_usec) / 1000;
120                         eDebug("%d ms latency (%d fps)", diff, t * 1000 / (diff ? diff : 1));
121                         l = now;
122                         t = 0;
123                 }
124
125                 ++t;
126
127                 fb->waitVSync();
128                 break;
129         }
130         default:
131                 gDC::exec(o);
132                 break;
133         }
134 }
135
136 void gFBDC::setAlpha(int a)
137 {
138         alpha=a;
139
140         calcRamp();
141         setPalette();
142 }
143
144 void gFBDC::setBrightness(int b)
145 {
146         brightness=b;
147
148         calcRamp();
149         setPalette();
150 }
151
152 void gFBDC::setGamma(int g)
153 {
154         gamma=g;
155
156         calcRamp();
157         setPalette();
158 }
159
160 void gFBDC::setResolution(int xres, int yres)
161 {
162         if ((m_xres == xres) && (m_yres == yres))
163                 return;
164
165         m_xres = xres; m_yres = yres;
166
167         fb->SetMode(m_xres, m_yres, 32);
168
169         for (int y=0; y<m_yres; y++)    // make whole screen transparent
170                 memset(fb->lfb+y*fb->Stride(), 0x00, fb->Stride());
171
172         surface.type = 0;
173         surface.x = m_xres;
174         surface.y = m_yres;
175         surface.bpp = 32;
176         surface.bypp = 4;
177         surface.stride = fb->Stride();
178         surface.data = fb->lfb;
179         surface.offset = 0;
180
181         surface.data_phys = 50*1024*1024; // FIXME
182
183         int fb_size = surface.stride * surface.y;
184
185         if (fb->getNumPages() > 1)
186         {
187                 m_enable_double_buffering = 1;
188                 surface_back.type = 0;
189                 surface_back.x = m_xres;
190                 surface_back.y = m_yres;
191                 surface_back.bpp = 32;
192                 surface_back.bypp = 4;
193                 surface_back.stride = fb->Stride();
194                 surface_back.offset = surface.y;
195                 surface_back.data = fb->lfb + fb_size;
196                 surface_back.data_phys = surface.data_phys + fb_size;
197
198                 fb_size *= 2;
199         } else
200                 m_enable_double_buffering = 0;
201
202         eDebug("%dkB available for acceleration surfaces.", (fb->Available() - fb_size)/1024);
203         eDebug("resolution: %d x %d x %d (stride: %d)", surface.x, surface.y, surface.bpp, fb->Stride());
204
205         if (gAccel::getInstance())
206                 gAccel::getInstance()->setAccelMemorySpace(fb->lfb + fb_size, surface.data_phys + fb_size, fb->Available() - fb_size);
207
208         if (!surface.clut.data)
209         {
210                 surface.clut.colors = 256;
211                 surface.clut.data = new gRGB[surface.clut.colors];
212                 memset(surface.clut.data, 0, sizeof(*surface.clut.data)*surface.clut.colors);
213         }
214
215         surface_back.clut = surface.clut;
216
217         m_pixmap = new gPixmap(&surface);
218 }
219
220 void gFBDC::saveSettings()
221 {
222 }
223
224 void gFBDC::reloadSettings()
225 {
226         alpha=255;
227         gamma=128;
228         brightness=128;
229
230         calcRamp();
231         setPalette();
232 }
233
234 // eAutoInitPtr<gFBDC> init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC");
235 #ifndef SDLDC
236 eAutoInitPtr<gFBDC> init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC");
237 #endif