]> git.vomp.tv Git - vompclient-marten.git/blob - osdopengl.cc
MoComp nearly bug free
[vompclient-marten.git] / osdopengl.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 \r
22 #include "osdopengl.h"\r
23 #include "mtd.h"\r
24 #include "videovpeogl.h"\r
25 #include "surfaceopengl.h"\r
26 \r
27 \r
28 #include "message.h"\r
29 #include "command.h"\r
30 \r
31 \r
32 #define  BACKBUFFER_WIDTH 1920\r
33 #define  BACKBUFFER_HEIGHT 1080\r
34 \r
35 \r
36 \r
37 \r
38 \r
39 \r
40 \r
41 OsdOpenGL::OsdOpenGL()\r
42 {\r
43   glmutex.Lock();\r
44 \r
45   external_driving=false;\r
46 \r
47   lastrendertime=getTimeMS();\r
48   display_height=0;\r
49   display_width=0;\r
50 \r
51 #ifdef BENCHMARK_FPS\r
52         last_benchmark_time=getTimeMS();\r
53         num_benchmark_frames=0;\r
54 #endif\r
55 \r
56   \r
57 }\r
58 \r
59 OsdOpenGL::~OsdOpenGL()\r
60 {\r
61 \r
62   if (initted) \r
63   {\r
64           threadStop();\r
65                 shutdown();\r
66   }\r
67 \r
68 \r
69   glmutex.Unlock();\r
70 }\r
71 \r
72 int OsdOpenGL::getFD()\r
73 {\r
74   if (!initted) return 0;\r
75   return fdOsd;\r
76 }\r
77 \r
78 Surface * OsdOpenGL::createNewSurface() {\r
79         return (Surface*)new SurfaceOpenGL();\r
80 }\r
81 \r
82 int OsdOpenGL::init(void* device)\r
83 {\r
84   if (initted) return 0;\r
85   Video* video = Video::getInstance();\r
86    //window=*((HWND*)device);\r
87   \r
88    // May be this device specific part should go to a device specific child class\r
89 \r
90    //init broadcom chipset (Move to video?)\r
91    bcm_host_init();\r
92 \r
93    //First get connection to egl\r
94    egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);\r
95 \r
96    if (egl_display==EGL_NO_DISPLAY) {\r
97            Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x",eglGetError());\r
98            glmutex.Unlock();\r
99            return 0;\r
100    }\r
101 \r
102 \r
103 \r
104    if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {\r
105            Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x",eglGetError());\r
106            glmutex.Unlock();\r
107            return 0;\r
108    }\r
109 \r
110    const char *query_str=eglQueryString(egl_display,EGL_CLIENT_APIS);\r
111    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
112    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());\r
113    query_str=eglQueryString(egl_display,EGL_EXTENSIONS);\r
114    if (query_str)    Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
115    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());\r
116 \r
117    const EGLint attributs[]={\r
118                  EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,\r
119          EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT,\r
120          EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,\r
121          EGL_NONE\r
122    }; // Here, we might have to select the resolution!\r
123 \r
124 \r
125    EGLint number;\r
126 \r
127    if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number)==EGL_FALSE) {\r
128            Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x",eglGetError());\r
129            glmutex.Unlock();\r
130            return 0;\r
131    }\r
132 \r
133    const EGLint attr_context[]={\r
134                    EGL_CONTEXT_CLIENT_VERSION,2,\r
135           EGL_NONE\r
136       };\r
137 \r
138    egl_context=eglCreateContext(egl_display,egl_ourconfig,EGL_NO_CONTEXT,attr_context);\r
139    if (egl_context==EGL_NO_CONTEXT) {\r
140            Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x",eglGetError());\r
141            glmutex.Unlock();\r
142            return 0;\r
143    }\r
144 \r
145    // warning broadcom specific, get display size!\r
146    display_width=display_height=0;\r
147    if (graphics_get_display_size(0, &display_width, &display_height)<0) {\r
148            Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");\r
149            glmutex.Unlock();\r
150            return 0;\r
151    }\r
152    Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);\r
153    VC_RECT_T dst_rect ={0,0,display_width,display_height};\r
154    VC_RECT_T src_rect={0,0,display_width<<16,display_height<<16};\r
155    DISPMANX_DISPLAY_HANDLE_T bcm_display;\r
156    DISPMANX_ELEMENT_HANDLE_T bcm_element;\r
157    DISPMANX_UPDATE_HANDLE_T  bcm_update;\r
158 \r
159 \r
160    bcm_display=vc_dispmanx_display_open(0);\r
161    bcm_update=vc_dispmanx_update_start(0);\r
162    bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,\r
163          2,&dst_rect, 0,\r
164          &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);\r
165 \r
166    vc_dispmanx_update_submit_sync(bcm_update);\r
167    static EGL_DISPMANX_WINDOW_T nativewindow;\r
168    nativewindow.element=bcm_element;\r
169    nativewindow.height=display_height;\r
170    nativewindow.width=display_width;\r
171 \r
172    egl_surface = eglCreateWindowSurface(egl_display,egl_ourconfig, &nativewindow,NULL );\r
173    if (egl_surface==EGL_NO_SURFACE) {\r
174            Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");\r
175            glmutex.Unlock();\r
176            return 0;\r
177    }\r
178 \r
179    if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
180            Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");\r
181            glmutex.Unlock();\r
182                    return 0;\r
183    }\r
184    // Test stuff\r
185 \r
186    query_str=(const char*)glGetString(GL_VERSION) ;\r
187    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
188    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());\r
189 \r
190    query_str=(const char*)glGetString(GL_VENDOR) ;\r
191    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
192    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());\r
193 \r
194    query_str=(const char*)glGetString(GL_RENDERER) ;\r
195    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
196    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());\r
197 \r
198    query_str=(const char*)glGetString(GL_EXTENSIONS) ;\r
199    if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);\r
200    else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());\r
201 \r
202 \r
203 \r
204 \r
205   //Now we will create the Screen\r
206   screen = (Surface*) new SurfaceOpenGL(Surface::SCREEN);\r
207 \r
208   screen->create(video->getScreenWidth(), video->getScreenHeight());\r
209   screen->display();\r
210   initted = 1; // must set this here or create surface won't work\r
211 \r
212   //glGenBuffers(1, &vB);\r
213   //glGenBuffers(1, &iB);\r
214 \r
215   //Preparing the Shaders\r
216 \r
217   if (!osd_shader.init()) {\r
218           Log::getInstance()->log("OSD", Log::WARN, "Init Osd Shader failed");\r
219           glmutex.Unlock();\r
220           return 0;\r
221   }\r
222   if (!yuv400_shader.init()) {\r
223           Log::getInstance()->log("OSD", Log::WARN, "Init Yuv400 Shader failed");\r
224           glmutex.Unlock();\r
225           return 0;\r
226   }\r
227 \r
228   if (!yuv444_shader.init()) {\r
229           Log::getInstance()->log("OSD", Log::WARN, "Init Yuv444 Shader failed");\r
230           glmutex.Unlock();\r
231           return 0;\r
232   }\r
233 \r
234  /* gen_shader=CreateShader(generic_vertex_shader, GL_VERTEX_SHADER);\r
235   osd_shader=CreateShader(osd_frag_shader, GL_FRAGMENT_SHADER);\r
236 \r
237   // Create the program for osd rendering\r
238   osd_program=glCreateProgram();\r
239   if (osd_program==0) {\r
240           Log::getInstance()->log("OSD", Log::WARN, "Creating glsl program failed!%d",glGetError());\r
241       return 0;\r
242   }\r
243   glAttachShader(osd_program,gen_shader);\r
244   glAttachShader(osd_program,osd_shader);\r
245   glBindAttribLocation(osd_program,0,"vec_pos");\r
246   glBindAttribLocation(osd_program,1,"tex_coord");\r
247 \r
248 \r
249 \r
250   glLinkProgram(osd_program);\r
251 \r
252 \r
253 \r
254   GLint link_status;\r
255   glGetProgramiv(osd_program,GL_LINK_STATUS, &link_status);\r
256 \r
257   if (!link_status) {\r
258           char buffer[1024];\r
259           glGetProgramInfoLog(osd_program,1024,NULL,buffer);\r
260           Log::getInstance()->log("OSD", Log::WARN, "Compiling Programm failed!");\r
261           Log::getInstance()->log("OSD", Log::WARN, "%s",buffer);\r
262           glDeleteProgram(osd_program);\r
263           return 0;\r
264   }\r
265 \r
266   osd_sampler_loc=glGetUniformLocation(osd_program,"texture");\r
267  //   Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",osd_sampler_loc,glGetError());\r
268 \r
269   // create the program for yuv frame rendering\r
270   frame_shader=CreateShader(frame_frag_shader, GL_FRAGMENT_SHADER);\r
271 \r
272   frame_program=glCreateProgram();\r
273   if (frame_program==0) {\r
274           Log::getInstance()->log("OSD", Log::WARN, "Creating glsl program failed!%d",glGetError());\r
275       return 0;\r
276   }\r
277   glAttachShader(frame_program,gen_shader);\r
278   glAttachShader(frame_program,frame_shader);\r
279   glBindAttribLocation(frame_program,0,"vec_pos");\r
280   glBindAttribLocation(frame_program,1,"tex_coord");\r
281 \r
282 \r
283 \r
284   glLinkProgram(frame_program);\r
285   //GLint link_status;\r
286   glGetProgramiv(frame_program,GL_LINK_STATUS, &link_status);\r
287 \r
288   if (!link_status) {\r
289           char buffer[1024];\r
290           glGetProgramInfoLog(frame_program,1024,NULL,buffer);\r
291           Log::getInstance()->log("OSD", Log::WARN, "Compiling Programm failed!");\r
292           Log::getInstance()->log("OSD", Log::WARN, "%s",buffer);\r
293           glDeleteProgram(frame_program);\r
294           return 0;\r
295   }\r
296 \r
297   frame_sampler_locY=glGetUniformLocation(frame_program,"textureY");\r
298  // Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locY,glGetError());\r
299   frame_sampler_locU=glGetUniformLocation(frame_program,"textureU");\r
300   //Log::getInstance()->log("OSD", Log::WARN, "uniform location %x %x",frame_sampler_locU,glGetError());\r
301    frame_sampler_locV=glGetUniformLocation(frame_program,"textureV");\r
302 */\r
303 \r
304 \r
305   glClearColor(0.0f,0.0f,0.0f,1.f);\r
306   eglSwapInterval(egl_display, 1 );\r
307 \r
308   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
309 \r
310   if (((VideoVPEOGL*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff\r
311           return 0;\r
312   }\r
313 \r
314 \r
315   glmutex.Unlock();\r
316   threadStart();\r
317 \r
318   return 1;\r
319 }\r
320 \r
321 \r
322 \r
323 \r
324         \r
325 void OsdOpenGL::InitVertexBuffer(float  scalex,float scaley)\r
326 {\r
327   Video* video=Video::getInstance();\r
328   float texx=1.f;\r
329   float texy=1.f;\r
330   OSDCOLOR osdcolor={1.f,1.f,1.f,1.f};\r
331 \r
332  // osdvertices[0].c=osdcolor;\r
333   osdvertices[0].x= (scalex);\r
334   osdvertices[0].y=-scaley;\r
335   osdvertices[0].z=0.5;\r
336   osdvertices[0].u=texx;\r
337   osdvertices[0].v=texy;\r
338  // osdvertices[1].c=osdcolor;\r
339   osdvertices[1].x=(scalex);\r
340   osdvertices[1].y=(scaley);\r
341   osdvertices[1].z=0.5f;\r
342   osdvertices[1].u=texx;\r
343   osdvertices[1].v=0.f;\r
344   //  osdvertices[0].c=osdcolor;\r
345   osdvertices[2].x=(-scalex);\r
346   osdvertices[2].y=-scaley;\r
347   osdvertices[2].z=0.5f;\r
348   osdvertices[2].u=0.f;\r
349   osdvertices[2].v=texy;\r
350  // osdvertices[3].c=osdcolor;\r
351   osdvertices[3].x=-scalex;\r
352   osdvertices[3].y=(scaley);\r
353   osdvertices[3].z=0.5f;\r
354   osdvertices[3].u=0.f;\r
355   osdvertices[3].v=0.f;\r
356   \r
357   osdindices[0]=0;\r
358   osdindices[1]=1;\r
359   osdindices[2]=2;\r
360   osdindices[3]=0;\r
361   osdindices[4]=2;\r
362   osdindices[5]=3;\r
363 \r
364 \r
365 \r
366 \r
367  // glBindBuffer(GL_ARRAY_BUFFER, vB);\r
368  // glBufferData(GL_ARRAY_BUFFER, sizeof(osdvertices), osdvertices, GL_STATIC_DRAW);\r
369 \r
370 \r
371  // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iB);\r
372   //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(osdindices), osdindices, GL_STATIC_DRAW);\r
373 \r
374 \r
375 \r
376   return;\r
377 }\r
378 \r
379 int OsdOpenGL::shutdown()\r
380 {\r
381   if (!initted) return 0;\r
382   initted = 0;\r
383 \r
384   (((VideoVPEOGL*)Video::getInstance())->shutdownUsingOSDObjects());\r
385 \r
386 \r
387   osd_shader.deinit();\r
388   yuv400_shader.deinit();\r
389   yuv444_shader.deinit();\r
390 \r
391   glClear(GL_COLOR_BUFFER_BIT);\r
392   eglSwapBuffers(egl_display, egl_surface);\r
393   eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
394   eglDestroySurface(egl_display,egl_surface);\r
395   eglDestroyContext(egl_display,egl_context);\r
396   eglTerminate(egl_display );\r
397 \r
398   return 1;\r
399 }\r
400 \r
401 void OsdOpenGL::screenShot(const char* fileName)\r
402 {\r
403   screen->screenShot(fileName);\r
404 }\r
405 \r
406 void OsdOpenGL::threadMethod()\r
407 {\r
408         // We have to claim the gl context for this thread\r
409         //glmutex.Lock();\r
410 \r
411         //glmutex.Unlock();\r
412         VPEOGLFrame *frame=NULL;\r
413         int ts=0;\r
414         VideoVPEOGL* video =(VideoVPEOGL*) Video::getInstance();\r
415         while (true)\r
416         {\r
417                 ts=10;\r
418                 unsigned int waittime=10;\r
419                 if (initted){\r
420                         if (!frame) frame=video->getReadyOGLFrame();\r
421                         if (frame) {\r
422                                 InternalRendering(frame);\r
423                                 //MILLISLEEP(1000);\r
424                                 lastrendertime=getTimeMS();\r
425                                 video->returnOGLFrame(frame); //please recycle it\r
426                                 frame=NULL;\r
427                         } else {\r
428                                  long long time1=getTimeMS();\r
429                                  if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing\r
430                                         InternalRendering(NULL);\r
431                                         lastrendertime=getTimeMS();\r
432                                  }\r
433                         }\r
434                         frame=video->getReadyOGLFrame();\r
435                 }\r
436 \r
437                 if (frame) ts=0;\r
438                 threadCheckExit();\r
439                 if (ts!=0) {\r
440                         struct timespec target_time;\r
441                         clock_gettime(CLOCK_REALTIME,&target_time);\r
442                         target_time.tv_nsec+=1000000LL*ts;\r
443                         if (target_time.tv_nsec>999999999) {\r
444                                 target_time.tv_nsec-=1000000000L;\r
445                                 target_time.tv_sec+=1;\r
446                         }\r
447                         threadWaitForSignalTimed(&target_time);\r
448                 }\r
449                 //Sleep(1);\r
450         }\r
451         //eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
452 }\r
453 \r
454 \r
455 void OsdOpenGL::threadPostStopCleanup()\r
456 {\r
457         //Doing nothing\r
458         //goo;\r
459 }\r
460 \r
461 /*\r
462 // This function is called from the WinMain function in order to get Screen updates\r
463 void OsdOpenGL::Render()\r
464 {\r
465         if (!initted) return ;\r
466         VPEOGLFrame* frame=NULL;\r
467         if (external_driving) {\r
468         long long time1=getTimeMS();\r
469                 if ((time1-lastrendertime)>200) {//5 fps for OSD updates are enough, avoids tearing\r
470                         InternalRendering(NULL);\r
471                         lastrendertime=getTimeMS();\r
472         } else {\r
473                    //Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads\r
474         }\r
475         } else {\r
476                 struct timespec ts;\r
477                 clock_gettime(CLOCK_MONOTONIC, &ts);\r
478                 long long time1=ts.tv_sec*1000+ts.tv_nsec/1000000LL;\r
479                 if ((time1-lastrendertime)>100) {//10 fps for OSD updates are enough, avoids tearing\r
480                         InternalRendering(NULL);\r
481                         lastrendertime=getTimeMS();\r
482                 } else {\r
483                         //Sleep(5);\r
484                 \r
485                 }\r
486                 \r
487         }\r
488 }\r
489 \r
490 void OsdOpenGL::RenderDS(VPEOGLFrame* frame){\r
491         if (!initted) return; \r
492         if (external_driving) {\r
493                 InternalRendering(frame);\r
494                 lastrendertime=getTimeMS();\r
495         }\r
496 }*/\r
497 \r
498 \r
499 void OsdOpenGL::InternalRendering(VPEOGLFrame* frame){\r
500     BeginPainting();\r
501   /*  HRESULT losty=d3ddevice->TestCooperativeLevel();\r
502     if (losty==D3DERR_DEVICELOST) {\r
503         //Sleep(10);\r
504                 EndPainting();\r
505         return; //Device Lost\r
506     }\r
507     if (losty==D3DERR_DEVICENOTRESET){\r
508            EndPainting();\r
509        DoLost();\r
510        return;\r
511     }\r
512         WaitForSingleObject(event,INFINITE);\r
513         */\r
514    \r
515         \r
516 /*\r
517     LPDIRECT3DSURFACE9 targetsurf;\r
518         if (swappy)\r
519         {\r
520                 targetsurf=swapsurf;\r
521                 d3ddevice->SetRenderTarget(0,swapsurf);//Stupid VMR manipulates the render target\r
522         } \r
523         else\r
524         {\r
525                 targetsurf=d3drtsurf;\r
526                 d3ddevice->SetRenderTarget(0,d3drtsurf);//Stupid VMR manipulates the render target\r
527         }\r
528         D3DSURFACE_DESC targetdesc;\r
529         targetsurf->GetDesc(&targetdesc);\r
530 \r
531         if (external_driving) {\r
532                 //Copy video to Backbuffer\r
533                 if (present!=NULL ) {\r
534                         VideoWin* video =(VideoWin*) Video::getInstance();\r
535                         /*calculating destination rect *\r
536                         RECT destrect={0,0,/*video->getScreenWidth()* targetdesc.Width,\r
537                                 /*video->getScreenHeight()*targetdesc.Height};\r
538                         UCHAR mode=video->getMode();\r
539                         switch (mode) {\r
540                         case Video::EIGHTH:\r
541                         destrect.right=destrect.right/2;\r
542                         destrect.bottom=destrect.bottom/2;\r
543                         case Video::QUARTER:\r
544                         destrect.right=destrect.right/2+video->getPosx()*2;\r
545                         destrect.bottom=destrect.bottom/2+video->getPosy()*2;\r
546                         destrect.left=video->getPosx()*2;\r
547                         destrect.top=video->getPosy()*2;\r
548                         d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);\r
549                         break;\r
550                         };\r
551                         D3DSURFACE_DESC surf_desc;\r
552                         present->GetDesc(&surf_desc);//for chop sides\r
553                         RECT sourcerect= {0,0,surf_desc.Width,surf_desc.Height};\r
554                         if (video->getPseudoTVsize()==Video::ASPECT4X3 \r
555                                 && video->getMode()==Video::NORMAL \r
556                                 && video->getAspectRatio()==Video::ASPECT16X9) {\r
557                                         unsigned int correction=((double) (surf_desc.Width))*4.*9./3./16.;\r
558                                         sourcerect.left=(surf_desc.Width-correction)/2;\r
559                                         sourcerect.right=sourcerect.left+correction;\r
560                         }\r
561                         d3ddevice->StretchRect(present,&sourcerect,targetsurf ,&destrect,filter_type);\r
562 \r
563                 }\r
564         } else {\r
565                 VideoWin* video =(VideoWin*) Video::getInstance();\r
566                 //Clear Background\r
567                 if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);\r
568         }*/\r
569 \r
570 \r
571         //InitVertexBuffer(display_width,display_height);\r
572     InitVertexBuffer(1.f,1.f);\r
573 \r
574 \r
575         glViewport(0, 0, display_width,display_height);\r
576 \r
577         glClearColor(0.0f,0.0f,0.0f,1.f);\r
578         glClear(GL_COLOR_BUFFER_BIT);\r
579 \r
580 \r
581 \r
582 \r
583 \r
584         if (frame) {\r
585                 //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
586         /*      glUseProgram(frame_program);\r
587                 //Log::getInstance()->log("OSD", Log::WARN, "mark1 glerror %x",glGetError());\r
588                 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
589                 glEnableVertexAttribArray(0);\r
590                 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
591                 glEnableVertexAttribArray(1);\r
592 \r
593 \r
594                 //Log::getInstance()->log("OSD", Log::WARN, "mark2 glerror %x",glGetError());\r
595 \r
596 \r
597                 glActiveTexture(GL_TEXTURE2);\r
598                 glBindTexture(GL_TEXTURE_2D,frame->textures[2]);\r
599                 glUniform1i(frame_sampler_locV,2);\r
600                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
601                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);\r
602 \r
603 \r
604                 glActiveTexture(GL_TEXTURE1);\r
605                 glBindTexture(GL_TEXTURE_2D,frame->textures[1]);\r
606                 glUniform1i(frame_sampler_locU,1);\r
607                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
608                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);\r
609 \r
610 \r
611                 glActiveTexture(GL_TEXTURE0);\r
612                 glBindTexture(GL_TEXTURE_2D,frame->textures[0]);\r
613                 glUniform1i(frame_sampler_locY,0);\r
614                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
615                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);*/\r
616 \r
617                 switch (frame->type) {\r
618                 case 1:\r
619                         yuv400_shader.PrepareRendering(frame->textures[0],frame->textures[1],frame->textures[2]);break;\r
620                 case 2:\r
621                         yuv444_shader.PrepareRendering(frame->textures[0]);break;\r
622                 }\r
623 \r
624 \r
625 \r
626 \r
627                 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
628                 glEnableVertexAttribArray(0);\r
629                 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
630                 glEnableVertexAttribArray(1);\r
631 \r
632 \r
633                 //Log::getInstance()->log("OSD", Log::WARN, "mark8 glerror %x %x",glGetError(),osd_sampler_loc);\r
634 \r
635 \r
636 \r
637                 glDrawArrays(GL_TRIANGLE_STRIP, 0,  4);\r
638 \r
639 \r
640         }\r
641 \r
642 \r
643         /*glUseProgram(osd_program);\r
644         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
645         glEnableVertexAttribArray(0);\r
646         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
647         glEnableVertexAttribArray(1);\r
648 \r
649 \r
650         glActiveTexture(GL_TEXTURE0);\r
651         glBindTexture(GL_TEXTURE_2D,((SurfaceOpenGL*)screen)->getTexture());\r
652 \r
653         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);\r
654         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);\r
655 \r
656         glUniform1i(osd_sampler_loc,0);*/\r
657 \r
658         osd_shader.PrepareRendering(((SurfaceOpenGL*)screen)->getTexture());\r
659 \r
660         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);\r
661         glEnableVertexAttribArray(0);\r
662         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));\r
663         glEnableVertexAttribArray(1);\r
664 \r
665 \r
666         if (frame!=NULL) { //This is ok for ffmpeg rendering not OMX\r
667                 glEnable(GL_BLEND);\r
668                 glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ZERO,GL_ONE);\r
669 \r
670         } else {\r
671                 glDisable(GL_BLEND);\r
672         }\r
673 \r
674 \r
675         glDrawArrays(GL_TRIANGLE_STRIP, 0,  4);\r
676 \r
677         \r
678 \r
679         //Show it to the user!\r
680         eglSwapBuffers(egl_display, egl_surface);\r
681 \r
682         EndPainting();\r
683 #ifdef BENCHMARK_FPS\r
684         num_benchmark_frames++;\r
685         if (getTimeMS()-last_benchmark_time>4000) {\r
686                 float fps=1000./(float)(getTimeMS()-last_benchmark_time);\r
687                 fps*=((float)num_benchmark_frames);\r
688                 num_benchmark_frames=0;\r
689                 Log::getInstance()->log("OSD", Log::NOTICE, "Current FPS %g", fps);\r
690                 last_benchmark_time=getTimeMS();\r
691 \r
692         }\r
693 \r
694 #endif\r
695 \r
696         \r
697 //      if (!external_driving) {\r
698 //              Sleep(4);//The User can wait for 4 milliseconds to see his changes\r
699 //      }\r
700 }\r
701 \r
702 bool OsdOpenGL::DoLost(){\r
703         /*\r
704         Log::getInstance()->log("OSD", Log::WARN, "Direct3D Device Lost! Reobtaining...");\r
705         ResetEvent(event);\r
706         if (external_driving && dsallocator!=NULL) {\r
707                 dsallocator->LostDevice(d3ddevice,d3d); //Propagate the information through DS\r
708         }\r
709         //First we free up all resources\r
710         Video* video = Video::getInstance();\r
711         ((SurfaceWin*)screen)->ReleaseSurface();\r
712         if (d3drtsurf) d3drtsurf->Release();\r
713     d3drtsurf=NULL;\r
714         D3DPRESENT_PARAMETERS d3dparas;\r
715         ZeroMemory(&d3dparas,sizeof(d3dparas));\r
716         d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;\r
717         d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;\r
718         d3dparas.Windowed=TRUE;\r
719         d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
720 \r
721         if (swapsurf) {swapsurf->Release();swapsurf=NULL;};\r
722         if (swappy) {swappy->Release();swappy=NULL;};\r
723 \r
724         if (d3ddevice->Reset(&d3dparas)!=D3D_OK){\r
725                 return false;\r
726         }\r
727     d3ddevice->GetRenderTarget(0,&d3drtsurf);\r
728         if (d3ddevman) d3ddevman->ResetDevice(d3ddevice,dxvatoken);\r
729         //InitVertexBuffer();\r
730     //Redraw Views, Chris could you add a member function to BoxStack, so that\r
731         // I can cause it to completely redraw the Views?\r
732         // Otherwise the OSD would be distorted after Device Lost\r
733         // FIXME\r
734         \r
735         SetEvent(event);\r
736 \r
737 \r
738         screen->create(video->getScreenWidth(), video->getScreenHeight());\r
739         screen->display();*/\r
740         \r
741         return true;\r
742 \r
743 }\r
744 \r
745 \r
746 void OsdOpenGL::BeginPainting() {//We synchronize calls to d3d between different threads\r
747         glmutex.Lock();\r
748         if (initted) {\r
749                 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {\r
750                         Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %d",eglGetError());\r
751                         return;\r
752                 }\r
753         }\r
754 }\r
755 \r
756 void OsdOpenGL::EndPainting() {\r
757         eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
758         glmutex.Unlock();\r
759 }\r
760 \r
761 void OsdOpenGL::setExternalDriving(/*DsAllocator* dsall,*/unsigned int  width, unsigned height) {\r
762         /*\r
763         if (swappy)\r
764         {\r
765                 BeginPainting();\r
766                 d3ddevice->StretchRect(swapsurf,NULL,d3drtsurf,NULL,filter_type);\r
767                 LPDIRECT3DSWAPCHAIN9 temp=swappy;\r
768                 LPDIRECT3DSURFACE9 tempsurf=swapsurf;\r
769                 swappy=NULL;\r
770                 swapsurf=NULL;\r
771                 EndPainting();\r
772                 tempsurf->Release();\r
773                 temp->Release();\r
774         }\r
775 \r
776         if (dsall==NULL) {\r
777                 external_driving=false;\r
778                 dsallocator=NULL;       \r
779                 return;\r
780         }\r
781         WaitForSingleObject(event,INFINITE);//We will only return if we are initted\r
782         BeginPainting();\r
783 \r
784         if (width>BACKBUFFER_WIDTH || height>BACKBUFFER_HEIGHT) \r
785         {\r
786                 D3DPRESENT_PARAMETERS d3dparas;\r
787                 ZeroMemory(&d3dparas,sizeof(d3dparas));\r
788                 d3dparas.BackBufferWidth=width;\r
789                 d3dparas.BackBufferHeight=height;\r
790                 d3dparas.Windowed=TRUE;\r
791                 d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;\r
792                 if (d3ddevice->CreateAdditionalSwapChain(&d3dparas,&swappy)!=D3D_OK){\r
793                         Log::getInstance()->log("OSD", Log::WARN, "Could not create Swap Chain!");\r
794                         //return 0;\r
795                 } else {\r
796                         swappy->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&swapsurf);\r
797                 }\r
798         Log::getInstance()->log("OSD", Log::INFO, "Create Additional Swap Chain %d %d!",width,height);\r
799         }\r
800 \r
801         dsallocator=dsall;\r
802         external_driving=true;\r
803         \r
804         EndPainting();*/\r
805 }\r
806 \r
807 void OsdOpenGL::Blank() {\r
808         BeginPainting();\r
809         glClearColor(0.15f, 0.25f, 0.35f, 1.0f); // change this to black after testing\r
810         glClear( GL_COLOR_BUFFER_BIT );\r
811         glClear( GL_DEPTH_BUFFER_BIT );\r
812         EndPainting();\r
813 }\r