2 Copyright 2004-2005 Chris Tallon, 2006,2011-2012 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "osdopengl.h"
23 #include "surfaceopengl.h"
28 #define BACKBUFFER_WIDTH 1280
29 #define BACKBUFFER_HEIGHT 720
31 OsdOpenGL::OsdOpenGL()
35 external_driving=false;
37 lastrendertime=getTimeMS();
43 last_benchmark_time=getTimeMS();
44 num_benchmark_frames=0;
50 OsdOpenGL::~OsdOpenGL()
63 int OsdOpenGL::getFD()
65 if (!initted) return 0;
69 Surface * OsdOpenGL::createNewSurface() {
70 return (Surface*)new SurfaceOpenGL();
75 if (initted) return 0;
76 Video* video = Video::getInstance();
78 //init broadcom chipset (Move to video?)
81 //First get connection to egl
82 egl_display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
84 if (egl_display==EGL_NO_DISPLAY) {
85 Log::getInstance()->log("OSD", Log::WARN, "Could not get egl display! %x",eglGetError());
92 if (eglInitialize(egl_display, NULL, NULL)==EGL_FALSE) {
93 Log::getInstance()->log("OSD", Log::WARN, "Initialising display failed! %x",eglGetError());
98 const char *query_str=eglQueryString(egl_display,EGL_CLIENT_APIS);
99 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
100 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
101 query_str=eglQueryString(egl_display,EGL_EXTENSIONS);
102 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
103 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",eglGetError());
105 const EGLint attributs[]={
106 EGL_RED_SIZE,8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,
107 EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT,
108 EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
110 }; // Here, we might have to select the resolution!
115 if (eglChooseConfig(egl_display, attributs, &egl_ourconfig, 1, &number)==EGL_FALSE) {
116 Log::getInstance()->log("OSD", Log::WARN, "Choosing egl config failed! %x",eglGetError());
121 const EGLint attr_context[]={
122 EGL_CONTEXT_CLIENT_VERSION,2,
126 egl_context=eglCreateContext(egl_display,egl_ourconfig,EGL_NO_CONTEXT,attr_context);
127 if (egl_context==EGL_NO_CONTEXT) {
128 Log::getInstance()->log("OSD", Log::WARN, "Creating egl context failed! %x",eglGetError());
133 // warning broadcom specific, get display size!
134 display_width=display_height=0;
135 if (graphics_get_display_size(0, &display_width, &display_height)<0) {
136 Log::getInstance()->log("OSD", Log::WARN, "Getting display size failed! (BCM API) ");
140 Log::getInstance()->log("OSD", Log::NOTICE, "Displaysize is %d x %d ",display_width, display_height);
141 VC_RECT_T dst_rect ={0,0,display_width,display_height};
142 VC_RECT_T src_rect={0,0,BACKBUFFER_WIDTH <<16,BACKBUFFER_HEIGHT<<16};
144 DISPMANX_UPDATE_HANDLE_T bcm_update;
146 bcm_display=vc_dispmanx_display_open(0);
147 bcm_update=vc_dispmanx_update_start(0);
148 bcm_element=vc_dispmanx_element_add(bcm_update,bcm_display,
150 &src_rect,DISPMANX_PROTECTION_NONE,0, 0, (DISPMANX_TRANSFORM_T) 0);
152 vc_dispmanx_update_submit_sync(bcm_update);
153 static EGL_DISPMANX_WINDOW_T nativewindow;
154 nativewindow.element=bcm_element;
155 nativewindow.height=BACKBUFFER_HEIGHT;
156 nativewindow.width=BACKBUFFER_WIDTH;
158 egl_surface = eglCreateWindowSurface(egl_display,egl_ourconfig, &nativewindow,NULL );
159 if (egl_surface==EGL_NO_SURFACE) {
160 Log::getInstance()->log("OSD", Log::WARN, "Creating egl window surface failed!");
165 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
166 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed");
172 query_str=(const char*)glGetString(GL_VERSION) ;
173 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
174 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
176 query_str=(const char*)glGetString(GL_VENDOR) ;
177 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
178 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
180 query_str=(const char*)glGetString(GL_RENDERER) ;
181 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
182 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
184 query_str=(const char*)glGetString(GL_EXTENSIONS) ;
185 if (query_str) Log::getInstance()->logLongString("OSD", Log::NOTICE, query_str);
186 else Log::getInstance()->log("OSD", Log::WARN, "Could not query display %x",glGetError());
191 //Now we will create the Screen
192 screen = (Surface*) new SurfaceOpenGL(Surface::SCREEN);
194 screen->create(video->getScreenWidth(), video->getScreenHeight());
196 initted = 1; // must set this here or create surface won't work
198 //glGenBuffers(1, &vB);
199 //glGenBuffers(1, &iB);
201 //Preparing the Shaders
203 if (!osd_shader.init()) {
204 Log::getInstance()->log("OSD", Log::WARN, "Init Osd Shader failed");
212 glClearColor(0.0f,0.0f,0.0f,1.f);
213 eglSwapInterval(egl_display, 1 );
215 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
217 if (((VideoOMX*)Video::getInstance())->initUsingOSDObjects()!=1) { //call Video for init opengl stuff
228 void OsdOpenGL::InitVertexBuffer(float scalex,float scaley)
230 Video* video=Video::getInstance();
233 OSDCOLOR osdcolor={1.f,1.f,1.f,1.f};
235 // osdvertices[0].c=osdcolor;
236 osdvertices[0].x= (scalex);
237 osdvertices[0].y=-scaley;
238 osdvertices[0].z=0.5;
239 osdvertices[0].u=texx;
240 osdvertices[0].v=texy;
241 // osdvertices[1].c=osdcolor;
242 osdvertices[1].x=(scalex);
243 osdvertices[1].y=(scaley);
244 osdvertices[1].z=0.5f;
245 osdvertices[1].u=texx;
246 osdvertices[1].v=0.f;
247 // osdvertices[0].c=osdcolor;
248 osdvertices[2].x=(-scalex);
249 osdvertices[2].y=-scaley;
250 osdvertices[2].z=0.5f;
251 osdvertices[2].u=0.f;
252 osdvertices[2].v=texy;
253 // osdvertices[3].c=osdcolor;
254 osdvertices[3].x=-scalex;
255 osdvertices[3].y=(scaley);
256 osdvertices[3].z=0.5f;
257 osdvertices[3].u=0.f;
258 osdvertices[3].v=0.f;
270 int OsdOpenGL::shutdown()
272 if (!initted) return 0;
279 (((VideoOMX*)Video::getInstance())->shutdownUsingOSDObjects());
284 glClear(GL_COLOR_BUFFER_BIT);
285 eglSwapBuffers(egl_display, egl_surface);
286 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
287 eglDestroySurface(egl_display,egl_surface);
288 eglDestroyContext(egl_display,egl_context);
289 eglTerminate(egl_display );
291 DISPMANX_UPDATE_HANDLE_T bcm_update;
292 bcm_update=vc_dispmanx_update_start(0);
294 vc_dispmanx_element_remove(bcm_update,bcm_element);
295 vc_dispmanx_update_submit_sync(bcm_update);
296 vc_dispmanx_display_close(bcm_display);
302 void OsdOpenGL::screenShot(const char* fileName)
305 screen->screenShot(fileName);
309 void OsdOpenGL::threadMethod()
311 // We have to claim the gl context for this thread
319 unsigned int waittime=10;
323 long long time1 = getTimeMS();
324 if ((time1 - lastrendertime) > 200) {//5 fps for OSD updates are enough, avoids tearing
326 lastrendertime = getTimeMS();
333 struct timespec target_time;
334 clock_gettime(CLOCK_REALTIME,&target_time);
335 target_time.tv_nsec+=1000000LL*ts;
336 if (target_time.tv_nsec>999999999) {
337 target_time.tv_nsec-=1000000000L;
338 target_time.tv_sec+=1;
340 threadWaitForSignalTimed(&target_time);
344 //eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
348 void OsdOpenGL::threadPostStopCleanup()
356 void OsdOpenGL::InternalRendering(){
363 //InitVertexBuffer(display_width,display_height);
364 InitVertexBuffer(1.f,1.f);
367 glViewport(0, 0, BACKBUFFER_WIDTH ,BACKBUFFER_HEIGHT);
369 glClearColor(0.0f,0.0f,0.0f,1.f);
370 glClear(GL_COLOR_BUFFER_BIT);
372 osd_shader.PrepareRendering(((SurfaceOpenGL*)screen)->getTexture());
374 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), osdvertices);
375 glEnableVertexAttribArray(0);
376 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,sizeof(OSDVERTEX), &(osdvertices[0].u));
377 glEnableVertexAttribArray(1);
385 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
389 //Show it to the user!
390 eglSwapBuffers(egl_display, egl_surface);
395 num_benchmark_frames++;
396 if (getTimeMS()-last_benchmark_time>4000) {
397 float fps=1000./(float)(getTimeMS()-last_benchmark_time);
398 fps*=((float)num_benchmark_frames);
399 num_benchmark_frames=0;
400 Log::getInstance()->log("OSD", Log::NOTICE, "Current FPS %g", fps);
401 last_benchmark_time=getTimeMS();
414 void OsdOpenGL::BeginPainting() {//We synchronize calls to d3d between different threads
417 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)== EGL_FALSE) {
418 Log::getInstance()->log("OSD", Log::WARN, "Making egl Current failed in thread %d",eglGetError());
424 void OsdOpenGL::EndPainting() {
425 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
431 void OsdOpenGL::Blank() {
433 glClearColor(0.15f, 1.f, 0.35f, 1.0f); // change this to black after testing
434 glClear( GL_COLOR_BUFFER_BIT );
435 glClear( GL_DEPTH_BUFFER_BIT );