]> git.vomp.tv Git - vompclient.git/blob - osdopengl.cc
MVP code removal
[vompclient.git] / osdopengl.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "osdopengl.h"
22 #include "videoomx.h"
23 #include "surfaceopengl.h"
24
25 #include "message.h"
26 #include "command.h"
27
28 #define  BACKBUFFER_WIDTH 1280
29 #define  BACKBUFFER_HEIGHT 720
30
31 OsdOpenGL::OsdOpenGL()
32 {
33   glmutex.Lock();
34
35   external_driving=false;
36
37   lastrendertime=getTimeMS();
38   display_height=0;
39   display_width=0;
40   mode=0;
41
42 #ifdef BENCHMARK_FPS
43         last_benchmark_time=getTimeMS();
44         num_benchmark_frames=0;
45 #endif
46
47   
48 }
49
50 OsdOpenGL::~OsdOpenGL()
51 {
52
53   if (initted) 
54   {
55           threadStop();
56                 shutdown();
57   }
58
59
60   glmutex.Unlock();
61 }
62
63 int OsdOpenGL::getFD()
64 {
65   if (!initted) return 0;
66   return fdOsd;
67 }
68
69 Surface * OsdOpenGL::createNewSurface() {
70         return (Surface*)new SurfaceOpenGL();
71 }
72
73 int OsdOpenGL::init(void* device)
74 {
75   if (initted) return 0;
76   Video* video = Video::getInstance();
77    //window=*((HWND*)device);
78   
79    // May be this device specific part should go to a device specific child class
80
81    //init broadcom chipset (Move to video?)
82
83
84    //First get connection to egl
85    egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
86
87    if (egl_display==EGL_NO_DISPLAY) {
88            Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x",eglGetError());
89            glmutex.Unlock();
90            return 0;
91    }
92
93
94
95    if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {
96            Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x",eglGetError());
97            glmutex.Unlock();
98            return 0;
99    }
100
101    const char *query_str=eglQueryString(egl_display,EGL_CLIENT_APIS);
102    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
103    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
104    query_str=eglQueryString(egl_display,EGL_EXTENSIONS);
105    if (query_str)    Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
106    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
107
108    const EGLint attributs[]={
109                  EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,
110          EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT,
111          EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
112          EGL_NONE
113    }; // Here, we might have to select the resolution!
114
115
116    EGLint number;
117
118    if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number)==EGL_FALSE) {
119            Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x",eglGetError());
120            glmutex.Unlock();
121            return 0;
122    }
123
124    const EGLint attr_context[]={
125                    EGL_CONTEXT_CLIENT_VERSION,2,
126           EGL_NONE
127       };
128
129    egl_context=eglCreateContext(egl_display,egl_ourconfig,EGL_NO_CONTEXT,attr_context);
130    if (egl_context==EGL_NO_CONTEXT) {
131            Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x",eglGetError());
132            glmutex.Unlock();
133            return 0;
134    }
135
136    // warning broadcom specific, get display size!
137    display_width=display_height=0;
138    if (graphics_get_display_size(0, &display_width, &display_height)<0) {
139            Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");
140            glmutex.Unlock();
141            return 0;
142    }
143    Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);
144    VC_RECT_T dst_rect ={0,0,display_width,display_height};
145    VC_RECT_T src_rect={0,0,BACKBUFFER_WIDTH <<16,BACKBUFFER_HEIGHT<<16};
146
147   DISPMANX_UPDATE_HANDLE_T  bcm_update;
148
149    bcm_display=vc_dispmanx_display_open(0);
150    bcm_update=vc_dispmanx_update_start(0);
151    bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,
152          2,&dst_rect, 0,
153          &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);
154
155    vc_dispmanx_update_submit_sync(bcm_update);
156    static EGL_DISPMANX_WINDOW_T nativewindow;
157    nativewindow.element=bcm_element;
158    nativewindow.height=BACKBUFFER_HEIGHT;
159    nativewindow.width=BACKBUFFER_WIDTH;
160
161    egl_surface = eglCreateWindowSurface(egl_display,egl_ourconfig, &nativewindow,NULL );
162    if (egl_surface==EGL_NO_SURFACE) {
163            Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");
164            glmutex.Unlock();
165            return 0;
166    }
167
168    if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
169            Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");
170            glmutex.Unlock();
171                    return 0;
172    }
173    // Test stuff
174
175    query_str=(const char*)glGetString(GL_VERSION) ;
176    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
177    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
178
179    query_str=(const char*)glGetString(GL_VENDOR) ;
180    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
181    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
182
183    query_str=(const char*)glGetString(GL_RENDERER) ;
184    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
185    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
186
187    query_str=(const char*)glGetString(GL_EXTENSIONS) ;
188    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
189    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
190
191
192
193
194   //Now we will create the Screen
195   screen = (Surface*) new SurfaceOpenGL(Surface::SCREEN);
196
197   screen->create(video->getScreenWidth(), video->getScreenHeight());
198   screen->display();
199   initted = 1; // must set this here or create surface won't work
200
201   //glGenBuffers(1, &vB);
202   //glGenBuffers(1, &iB);
203
204   //Preparing the Shaders
205
206   if (!osd_shader.init()) {
207           Log::getInstance()->log("OSD", Log::WARN, "Init Osd Shader failed");
208           glmutex.Unlock();
209           return 0;
210   }
211
212
213
214
215   glClearColor(0.0f,0.0f,0.0f,1.f);
216   eglSwapInterval(egl_display, 1 );
217
218   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
219
220   if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff
221           return 0;
222   }
223
224
225   glmutex.Unlock();
226   threadStart();
227
228   return 1;
229 }
230         
231 void OsdOpenGL::InitVertexBuffer(float  scalex,float scaley)
232 {
233   Video* video=Video::getInstance();
234   float texx=1.f;
235   float texy=1.f;
236   OSDCOLOR osdcolor={1.f,1.f,1.f,1.f};
237
238  // osdvertices[0].c=osdcolor;
239   osdvertices[0].x= (scalex);
240   osdvertices[0].y=-scaley;
241   osdvertices[0].z=0.5;
242   osdvertices[0].u=texx;
243   osdvertices[0].v=texy;
244  // osdvertices[1].c=osdcolor;
245   osdvertices[1].x=(scalex);
246   osdvertices[1].y=(scaley);
247   osdvertices[1].z=0.5f;
248   osdvertices[1].u=texx;
249   osdvertices[1].v=0.f;
250   //  osdvertices[0].c=osdcolor;
251   osdvertices[2].x=(-scalex);
252   osdvertices[2].y=-scaley;
253   osdvertices[2].z=0.5f;
254   osdvertices[2].u=0.f;
255   osdvertices[2].v=texy;
256  // osdvertices[3].c=osdcolor;
257   osdvertices[3].x=-scalex;
258   osdvertices[3].y=(scaley);
259   osdvertices[3].z=0.5f;
260   osdvertices[3].u=0.f;
261   osdvertices[3].v=0.f;
262   
263   osdindices[0]=0;
264   osdindices[1]=1;
265   osdindices[2]=2;
266   osdindices[3]=0;
267   osdindices[4]=2;
268   osdindices[5]=3;
269
270   return;
271 }
272
273 int OsdOpenGL::shutdown()
274 {
275   if (!initted) return 0;
276   glmutex.Lock();
277   initted = 0;
278   threadStop();
279   delete screen;
280   screen=NULL;
281
282   (((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());
283
284
285   osd_shader.deinit();
286
287   glClear(GL_COLOR_BUFFER_BIT);
288   eglSwapBuffers(egl_display, egl_surface);
289   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
290   eglDestroySurface(egl_display,egl_surface);
291   eglDestroyContext(egl_display,egl_context);
292   eglTerminate(egl_display );
293
294   DISPMANX_UPDATE_HANDLE_T  bcm_update;
295   bcm_update=vc_dispmanx_update_start(0);
296
297   vc_dispmanx_element_remove(bcm_update,bcm_element);
298   vc_dispmanx_update_submit_sync(bcm_update);
299   vc_dispmanx_display_close(bcm_display);
300
301
302   return 1;
303 }
304
305 void OsdOpenGL::screenShot(const char* fileName)
306 {
307   BeginPainting();
308   screen->screenShot(fileName);
309   EndPainting();
310 }
311
312 void OsdOpenGL::threadMethod()
313 {
314         // We have to claim the gl context for this thread
315         //glmutex.Lock();
316
317         //glmutex.Unlock();
318         int ts=0;
319         while (true)
320         {
321                 ts=10;
322                 unsigned int waittime=10;
323
324                 if (initted) {
325
326                         long long time1 = getTimeMS();
327                         if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing
328                                 InternalRendering();
329                                 lastrendertime = getTimeMS();
330
331                         }
332                 }
333
334                 threadCheckExit();
335                 if (ts!=0) {
336                         struct timespec target_time;
337                         clock_gettime(CLOCK_REALTIME,&target_time);
338                         target_time.tv_nsec+=1000000LL*ts;
339                         if (target_time.tv_nsec>999999999) {
340                                 target_time.tv_nsec-=1000000000L;
341                                 target_time.tv_sec+=1;
342                         }
343                         threadWaitForSignalTimed(&target_time);
344                 }
345                 //Sleep(1);
346         }
347         //eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
348 }
349
350
351 void OsdOpenGL::threadPostStopCleanup()
352 {
353         //Doing nothing
354         //goo;
355 }
356
357
358
359 void OsdOpenGL::InternalRendering(){
360
361     BeginPainting();
362
363
364
365
366         //InitVertexBuffer(display_width,display_height);
367     InitVertexBuffer(1.f,1.f);
368
369
370         glViewport(0, 0, BACKBUFFER_WIDTH ,BACKBUFFER_HEIGHT);
371
372         glClearColor(0.0f,0.0f,0.0f,1.f);
373         glClear(GL_COLOR_BUFFER_BIT);
374
375         osd_shader.PrepareRendering(((SurfaceOpenGL*)screen)->getTexture());
376
377         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);
378         glEnableVertexAttribArray(0);
379         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));
380         glEnableVertexAttribArray(1);
381
382
383
384         glDisable(GL_BLEND);
385
386
387
388         glDrawArrays(GL_TRIANGLE_STRIP, 0,  4);
389
390
391
392         //Show it to the user!
393         eglSwapBuffers(egl_display, egl_surface);
394
395         EndPainting();
396
397 #ifdef BENCHMARK_FPS
398         num_benchmark_frames++;
399         if (getTimeMS()-last_benchmark_time>4000) {
400                 float fps=1000./(float)(getTimeMS()-last_benchmark_time);
401                 fps*=((float)num_benchmark_frames);
402                 num_benchmark_frames=0;
403                 Log::getInstance()->log("OSD", Log::NOTICE, "Current FPS %g", fps);
404                 last_benchmark_time=getTimeMS();
405
406         }
407
408 #endif
409
410         
411
412 }
413
414
415
416
417 void OsdOpenGL::BeginPainting() {//We synchronize calls to d3d between different threads
418         glmutex.Lock();
419         if (initted) {
420                 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
421                         Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %d",eglGetError());
422                         return;
423                 }
424         }
425 }
426
427 void OsdOpenGL::EndPainting() {
428         eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
429         glmutex.Unlock();
430 }
431
432
433
434 void OsdOpenGL::Blank() {
435         BeginPainting();
436         glClearColor(0.15f, 1.f, 0.35f, 1.0f); // change this to black after testing
437         glClear( GL_COLOR_BUFFER_BIT );
438         glClear( GL_DEPTH_BUFFER_BIT );
439         EndPainting();
440 }