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