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