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