Support gles animation.
[vuplus_dvbapp] / 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 #ifdef USE_LIBVUGLES2
10 #include <vuplus_gles.h>
11 #endif
12
13 gFBDC::gFBDC()
14 {
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 }
31
32 void gFBDC::calcRamp()
33 {
34 #if 0
35         float fgamma=gamma ? gamma : 1;
36         fgamma/=10.0;
37         fgamma=1/log(fgamma);
38         for (int i=0; i<256; i++)
39         {
40                 float raw=i/255.0; // IIH, float.
41                 float corr=pow(raw, fgamma) * 256.0;
42
43                 int d=corr * (float)(256-brightness) / 256 + brightness;
44                 if (d < 0)
45                         d=0;
46                 if (d > 255)
47                         d=255;
48                 ramp[i]=d;
49
50                 rampalpha[i]=i*alpha/256;
51         }
52 #endif
53         for (int i=0; i<256; i++)
54         {
55                 int d;
56                 d=i;
57                 d=(d-128)*(gamma+64)/(128+64)+128;
58                 d+=brightness-128; // brightness correction
59                 if (d<0)
60                         d=0;
61                 if (d>255)
62                         d=255;
63                 ramp[i]=d;
64
65                 rampalpha[i]=i*alpha/256;
66         }
67
68         rampalpha[255]=255; // transparent BLEIBT bitte so.
69 }
70
71 void gFBDC::setPalette()
72 {
73         if (!surface.clut.data)
74                 return;
75
76         for (int i=0; i<256; ++i)
77         {
78                 fb->CMAP()->red[i]=ramp[surface.clut.data[i].r]<<8;
79                 fb->CMAP()->green[i]=ramp[surface.clut.data[i].g]<<8;
80                 fb->CMAP()->blue[i]=ramp[surface.clut.data[i].b]<<8;
81                 fb->CMAP()->transp[i]=rampalpha[surface.clut.data[i].a]<<8;
82         }
83         fb->PutCMAP();
84 }
85
86 void gFBDC::exec(const gOpcode *o)
87 {
88         switch (o->opcode)
89         {
90         case gOpcode::setPalette:
91         {
92                 gDC::exec(o);
93                 setPalette();
94                 break;
95         }
96         case gOpcode::flip:
97         {
98                 if (m_enable_double_buffering)
99                 {
100                         gSurface s(surface);
101                         surface = surface_back;
102                         surface_back = s;
103
104                         fb->setOffset(surface_back.offset);
105                 }
106                 break;
107         }
108         case gOpcode::waitVSync:
109         {
110                 static timeval l;
111                 static int t;
112                 timeval now;
113
114                 if (t == 1000)
115                 {
116                         gettimeofday(&now, 0);
117
118                         int diff = (now.tv_sec - l.tv_sec) * 1000 + (now.tv_usec - l.tv_usec) / 1000;
119                         eDebug("%d ms latency (%d fps)", diff, t * 1000 / (diff ? diff : 1));
120                         l = now;
121                         t = 0;
122                 }
123
124                 ++t;
125
126                 fb->blit();
127                 fb->waitVSync();
128                 break;
129         }
130         case gOpcode::flush:
131 #ifdef USE_LIBVUGLES2
132                 if (gles_is_animation())
133                         gles_do_animation();
134                 else
135                         fb->blit();
136 #else
137                 fb->blit();
138 #endif
139                 break;
140         case gOpcode::sendShow:
141         {
142 #ifdef USE_LIBVUGLES2
143                 gles_set_buffer((unsigned int *)surface.data);
144                 gles_set_animation(1, o->parm.setShowHideInfo->point.x(), o->parm.setShowHideInfo->point.y(), o->parm.setShowHideInfo->size.width(), o->parm.setShowHideInfo->size.height());
145 #endif
146                 break;
147         }
148         case gOpcode::sendHide:
149         {
150 #ifdef USE_LIBVUGLES2
151                 gles_set_buffer((unsigned int *)surface.data);
152                 gles_set_animation(0, o->parm.setShowHideInfo->point.x(), o->parm.setShowHideInfo->point.y(), o->parm.setShowHideInfo->size.width(), o->parm.setShowHideInfo->size.height());
153 #endif
154                 break;
155         }
156 #ifdef USE_LIBVUGLES2
157         case gOpcode::setView:
158         {
159                 gles_viewport(o->parm.setViewInfo->size.width(), o->parm.setViewInfo->size.height(), fb->Stride());
160                 break;
161         }
162 #endif
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::setResolution(int xres, int yres)
194 {
195         if ((m_xres == xres) && (m_yres == yres))
196                 return;
197
198         m_xres = xres; m_yres = yres;
199
200         fb->SetMode(m_xres, m_yres, 32);
201
202         for (int y=0; y<m_yres; y++)    // make whole screen transparent
203                 memset(fb->lfb+y*fb->Stride(), 0x00, fb->Stride());
204
205         surface.type = 0;
206         surface.x = m_xres;
207         surface.y = m_yres;
208         surface.bpp = 32;
209         surface.bypp = 4;
210         surface.stride = fb->Stride();
211         surface.data = fb->lfb;
212         surface.offset = 0;
213
214         surface.data_phys = fb->getPhysAddr();
215
216         int fb_size = surface.stride * surface.y;
217
218         if (fb->getNumPages() > 1)
219         {
220                 m_enable_double_buffering = 1;
221                 surface_back.type = 0;
222                 surface_back.x = m_xres;
223                 surface_back.y = m_yres;
224                 surface_back.bpp = 32;
225                 surface_back.bypp = 4;
226                 surface_back.stride = fb->Stride();
227                 surface_back.offset = surface.y;
228                 surface_back.data = fb->lfb + fb_size;
229                 surface_back.data_phys = surface.data_phys + fb_size;
230
231                 fb_size *= 2;
232         } else
233                 m_enable_double_buffering = 0;
234
235         eDebug("%dkB available for acceleration surfaces.", (fb->Available() - fb_size)/1024);
236         eDebug("resolution: %d x %d x %d (stride: %d)", surface.x, surface.y, surface.bpp, fb->Stride());
237
238         if (gAccel::getInstance())
239                 gAccel::getInstance()->setAccelMemorySpace(fb->lfb + fb_size, surface.data_phys + fb_size, fb->Available() - fb_size);
240
241         if (!surface.clut.data)
242         {
243                 surface.clut.colors = 256;
244                 surface.clut.data = new gRGB[surface.clut.colors];
245                 memset(surface.clut.data, 0, sizeof(*surface.clut.data)*surface.clut.colors);
246         }
247
248         surface_back.clut = surface.clut;
249
250         m_pixmap = new gPixmap(&surface);
251 }
252
253 void gFBDC::saveSettings()
254 {
255 }
256
257 void gFBDC::reloadSettings()
258 {
259         alpha=255;
260         gamma=128;
261         brightness=128;
262
263         calcRamp();
264         setPalette();
265 }
266
267 eAutoInitPtr<gFBDC> init_gFBDC(eAutoInitNumbers::graphic-1, "GFBDC");