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