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