Merge pull request #3819 from arnova/subtitles_for_stacks
[vuplus_xbmc] / xbmc / windowing / egl / EGLNativeTypeRaspberryPI.cpp
1 /*
2  *      Copyright (C) 2011-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 #include "system.h"
21
22 #include <EGL/egl.h>
23 #include "EGLNativeTypeRaspberryPI.h"
24 #include "utils/log.h"
25 #include "guilib/gui3d.h"
26 #include "linux/DllBCM.h"
27 #include "utils/StringUtils.h"
28 #include "settings/Settings.h"
29
30 #ifndef __VIDEOCORE4__
31 #define __VIDEOCORE4__
32 #endif
33
34 #define __VCCOREVER__ 0x04000000
35
36 #define IS_WIDESCREEN(m) ( m == 3 || m == 7 || m == 9 || \
37     m == 11 || m == 13 || m == 15 || m == 18 || m == 22 || \
38     m == 24 || m == 26 || m == 28 || m == 30 || m == 36 || \
39     m == 38 || m == 43 || m == 45 || m == 49 || m == 51 || \
40     m == 53 || m == 55 || m == 57 || m == 59)
41
42 #define MAKEFLAGS(group, mode, interlace) \
43   ( ( (mode)<<24 ) | ( (group)<<16 ) | \
44    ( (interlace) != 0 ? D3DPRESENTFLAG_INTERLACED : D3DPRESENTFLAG_PROGRESSIVE) | \
45    ( ((group) == HDMI_RES_GROUP_CEA && IS_WIDESCREEN(mode) ) ? D3DPRESENTFLAG_WIDESCREEN : 0) )
46
47 #define GETFLAGS_GROUP(f)       ( (HDMI_RES_GROUP_T)( ((f) >> 16) & 0xff ))
48 #define GETFLAGS_MODE(f)        ( ( (f) >>24 ) & 0xff )
49
50 //#ifndef DEBUG_PRINT
51 //#define DEBUG_PRINT 1
52 //#endif
53
54 #if defined(DEBUG_PRINT)
55 # define DLOG(fmt, args...) printf(fmt, ##args)
56 #else
57 # define DLOG(fmt, args...)
58 #endif
59
60
61 CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI()
62 {
63 #if defined(TARGET_RASPBERRY_PI)
64   m_DllBcmHost    = NULL;
65   m_nativeWindow  = NULL;
66 #endif
67 }
68
69 CEGLNativeTypeRaspberryPI::~CEGLNativeTypeRaspberryPI()
70 {
71 #if defined(TARGET_RASPBERRY_PI)
72   delete m_DllBcmHost;
73   if(m_nativeWindow)
74     free(m_nativeWindow);
75 #endif
76
77
78 bool CEGLNativeTypeRaspberryPI::CheckCompatibility()
79 {
80 #if defined(TARGET_RASPBERRY_PI)
81   DLOG("CEGLNativeTypeRaspberryPI::CheckCompatibility\n");
82   return true;
83 #else
84   return false;
85 #endif
86 }
87
88 void CEGLNativeTypeRaspberryPI::Initialize()
89 {
90 #if defined(TARGET_RASPBERRY_PI)
91   m_DllBcmHost              = NULL;
92   m_dispman_element         = DISPMANX_NO_HANDLE;
93   m_dispman_display         = DISPMANX_NO_HANDLE;
94
95   m_width                   = 1280;
96   m_height                  = 720;
97   m_initDesktopRes          = true;
98
99   m_DllBcmHost = new DllBcmHost;
100   m_DllBcmHost->Load();
101 #endif
102 }
103
104 void CEGLNativeTypeRaspberryPI::Destroy()
105 {
106 #if defined(TARGET_RASPBERRY_PI)
107   if(m_DllBcmHost && m_DllBcmHost->IsLoaded())
108     m_DllBcmHost->Unload();
109   delete m_DllBcmHost;
110   m_DllBcmHost = NULL;
111 #endif
112 }
113
114 bool CEGLNativeTypeRaspberryPI::CreateNativeDisplay()
115 {
116   m_nativeDisplay = EGL_DEFAULT_DISPLAY;
117   return true;
118 }
119
120 bool CEGLNativeTypeRaspberryPI::CreateNativeWindow()
121 {
122 #if defined(TARGET_RASPBERRY_PI)
123   if(!m_nativeWindow)
124     m_nativeWindow = (EGLNativeWindowType) calloc(1,sizeof( EGL_DISPMANX_WINDOW_T));
125   DLOG("CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI\n");
126   return true;
127 #else
128   return false;
129 #endif
130 }
131
132 bool CEGLNativeTypeRaspberryPI::GetNativeDisplay(XBNativeDisplayType **nativeDisplay) const
133 {
134   if (!nativeDisplay)
135     return false;
136   *nativeDisplay = (XBNativeDisplayType*) &m_nativeDisplay;
137   return true;
138 }
139
140 bool CEGLNativeTypeRaspberryPI::GetNativeWindow(XBNativeDisplayType **nativeWindow) const
141 {
142   DLOG("CEGLNativeTypeRaspberryPI::GetNativeWindow\n");
143   if (!nativeWindow)
144     return false;
145   *nativeWindow = (XBNativeWindowType*) &m_nativeWindow;
146   return true;
147 }  
148
149 bool CEGLNativeTypeRaspberryPI::DestroyNativeDisplay()
150 {
151   DLOG("CEGLNativeTypeRaspberryPI::DestroyNativeDisplay\n");
152   return true;
153 }
154
155 bool CEGLNativeTypeRaspberryPI::DestroyNativeWindow()
156 {
157 #if defined(TARGET_RASPBERRY_PI)
158   DestroyDispmaxWindow();
159   free(m_nativeWindow);
160   m_nativeWindow = NULL;
161   DLOG("CEGLNativeTypeRaspberryPI::DestroyNativeWindow\n");
162   return true;
163 #else
164   return false;
165 #endif  
166 }
167
168 bool CEGLNativeTypeRaspberryPI::GetNativeResolution(RESOLUTION_INFO *res) const
169 {
170 #if defined(TARGET_RASPBERRY_PI)
171   *res = m_desktopRes;
172
173   DLOG("CEGLNativeTypeRaspberryPI::GetNativeResolution %s\n", res->strMode.c_str());
174   return true;
175 #else
176   return false;
177 #endif
178 }
179
180 #if defined(TARGET_RASPBERRY_PI)
181 int CEGLNativeTypeRaspberryPI::FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions)
182 {
183   for (int i = 0; i < (int)resolutions.size(); i++)
184   {
185     if(resolutions[i].iScreenWidth == res.iScreenWidth && resolutions[i].iScreenHeight == res.iScreenHeight && resolutions[i].fRefreshRate == res.fRefreshRate &&
186       (resolutions[i].dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)) == (res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)))
187     {
188        return i;
189     }
190   }
191   return -1;
192 }
193 #endif
194
195 #if defined(TARGET_RASPBERRY_PI)
196 int CEGLNativeTypeRaspberryPI::AddUniqueResolution(const RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions)
197 {
198   int i = FindMatchingResolution(res, resolutions);
199   if (i>=0)
200   {  // don't replace a progressive resolution with an interlaced one of same resolution
201      if (!(res.dwFlags & D3DPRESENTFLAG_INTERLACED))
202        resolutions[i] = res;
203   }
204   else
205   {
206      resolutions.push_back(res);
207   }
208   return i;
209 }
210 #endif
211
212 bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res)
213 {
214 #if defined(TARGET_RASPBERRY_PI)
215   if(!m_DllBcmHost || !m_nativeWindow)
216     return false;
217
218   DestroyDispmaxWindow();
219
220   if(!m_fixedMode && GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags))
221   {
222     sem_init(&m_tv_synced, 0, 0);
223     m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this);
224
225     if (res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))
226     {
227       /* inform TV of any 3D settings. Note this property just applies to next hdmi mode change, so no need to call for 2D modes */
228       HDMI_PROPERTY_PARAM_T property;
229       property.property = HDMI_PROPERTY_3D_STRUCTURE;
230       if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
231         property.param1 = HDMI_3D_FORMAT_SBS_HALF;
232       else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB)
233         property.param1 = HDMI_3D_FORMAT_TB_HALF;
234       else
235         property.param1 = HDMI_3D_FORMAT_NONE;
236       property.param2 = 0;
237       vc_tv_hdmi_set_property(&property);
238     }
239     int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags));
240
241     if (success == 0)
242     {
243       CLog::Log(LOGDEBUG, "EGL set HDMI mode (%d,%d)=%d%s%s\n",
244                           GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
245                           (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? " SBS":"",
246                           (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? " TB":"");
247
248       sem_wait(&m_tv_synced);
249     }
250     else
251     {
252       CLog::Log(LOGERROR, "EGL failed to set HDMI mode (%d,%d)=%d%s%s\n",
253                           GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
254                           (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? " SBS":"",
255                           (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? " TB":"");
256     }
257     m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback);
258     sem_destroy(&m_tv_synced);
259
260     m_desktopRes = res;
261   }
262
263   m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0);
264
265   m_width   = res.iWidth;
266   m_height  = res.iHeight;
267
268   VC_RECT_T dst_rect;
269   VC_RECT_T src_rect;
270
271   dst_rect.x      = 0;
272   dst_rect.y      = 0;
273   dst_rect.width  = res.iScreenWidth;
274   dst_rect.height = res.iScreenHeight;
275
276   src_rect.x      = 0;
277   src_rect.y      = 0;
278   src_rect.width  = m_width << 16;
279   src_rect.height = m_height << 16;
280
281   VC_DISPMANX_ALPHA_T alpha;
282   memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
283   alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;
284
285   DISPMANX_CLAMP_T clamp;
286   memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T));
287
288   DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE;
289   DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0);
290
291   CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps (%d,%d) flags:%x aspect:%.2f\n",
292       m_width, m_height, dst_rect.width, dst_rect.height, res.fRefreshRate, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), (int)res.dwFlags, res.fPixelRatio);
293
294   m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
295     m_dispman_display,
296     1,                              // layer
297     &dst_rect,
298     (DISPMANX_RESOURCE_HANDLE_T)0,  // src
299     &src_rect,
300     DISPMANX_PROTECTION_NONE,
301     &alpha,                         //alphe
302     &clamp,                         //clamp
303     transform);                     // transform
304
305   assert(m_dispman_element != DISPMANX_NO_HANDLE);
306   assert(m_dispman_element != (unsigned)DISPMANX_INVALID);
307
308   memset(m_nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T));
309
310   EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow;
311
312   nativeWindow->element = m_dispman_element;
313   nativeWindow->width   = m_width;
314   nativeWindow->height  = m_height;
315
316   m_DllBcmHost->vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00);
317   m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update);
318
319   DLOG("CEGLNativeTypeRaspberryPI::SetNativeResolution\n");
320
321   return true;
322 #else
323   return false;
324 #endif
325 }
326
327 #if defined(TARGET_RASPBERRY_PI)
328 static float get_display_aspect_ratio(HDMI_ASPECT_T aspect)
329 {
330   float display_aspect;
331   switch (aspect) {
332     case HDMI_ASPECT_4_3:   display_aspect = 4.0/3.0;   break;
333     case HDMI_ASPECT_14_9:  display_aspect = 14.0/9.0;  break;
334     case HDMI_ASPECT_16_9:  display_aspect = 16.0/9.0;  break;
335     case HDMI_ASPECT_5_4:   display_aspect = 5.0/4.0;   break;
336     case HDMI_ASPECT_16_10: display_aspect = 16.0/10.0; break;
337     case HDMI_ASPECT_15_9:  display_aspect = 15.0/9.0;  break;
338     case HDMI_ASPECT_64_27: display_aspect = 64.0/27.0; break;
339     default:                display_aspect = 16.0/9.0;  break;
340   }
341   return display_aspect;
342 }
343
344 static float get_display_aspect_ratio(SDTV_ASPECT_T aspect)
345 {
346   float display_aspect;
347   switch (aspect) {
348     case SDTV_ASPECT_4_3:  display_aspect = 4.0/3.0;  break;
349     case SDTV_ASPECT_14_9: display_aspect = 14.0/9.0; break;
350     case SDTV_ASPECT_16_9: display_aspect = 16.0/9.0; break;
351     default:               display_aspect = 4.0/3.0;  break;
352   }
353   return display_aspect;
354 }
355
356 static bool ClampToGUIDisplayLimits(int &width, int &height)
357 {
358   float max_height = (float)CSettings::Get().GetInt("videoscreen.limitgui");
359   float default_ar = 16.0f/9.0f;
360   if (max_height < 540.0f || max_height > 1080.0f)
361     max_height = 1080.0f;
362
363   float ar = (float)width/(float)height;
364   float max_width = max_height * default_ar;
365   // bigger than maximum, so need to clamp
366   if (width > max_width || height > max_height) {
367     // wider than max, so clamp width first
368     if (ar > default_ar)
369     {
370       width = max_width;
371       height = max_width / ar + 0.5f;
372     // taller than max, so clamp height first
373     } else {
374       height = max_height;
375       width = max_height * ar + 0.5f;
376     }
377     return true;
378   }
379
380   return false;
381 }
382
383 static void SetResolutionString(RESOLUTION_INFO &res)
384 {
385   int gui_width  = res.iScreenWidth;
386   int gui_height = res.iScreenHeight;
387
388   ClampToGUIDisplayLimits(gui_width, gui_height);
389
390   res.iWidth = gui_width;
391   res.iHeight = gui_height;
392
393   res.strMode = StringUtils::Format("%dx%d (%dx%d) @ %.2f%s%s%s - Full Screen", res.iScreenWidth, res.iScreenHeight, res.iWidth, res.iHeight, res.fRefreshRate,
394     res.dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "",
395     res.dwFlags & D3DPRESENTFLAG_MODE3DTB   ? " 3DTB" : "",
396     res.dwFlags & D3DPRESENTFLAG_MODE3DSBS  ? " 3DSBS" : "");
397 }
398 #endif
399
400 bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions)
401 {
402 #if defined(TARGET_RASPBERRY_PI)
403   resolutions.clear();
404
405   if(!m_DllBcmHost)
406     return false;
407
408   m_fixedMode               = false;
409
410   /* read initial desktop resolution before probe resolutions.
411    * probing will replace the desktop resolution when it finds the same one.
412    * we raplace it because probing will generate more detailed 
413    * resolution flags we don't get with vc_tv_get_state.
414    */
415
416   if(m_initDesktopRes)
417   {
418     TV_DISPLAY_STATE_T tv_state;
419
420     // get current display settings state
421     memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T));
422     m_DllBcmHost->vc_tv_get_display_state(&tv_state);
423
424     if ((tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) != 0) // hdtv
425     {
426       m_desktopRes.iScreen      = 0;
427       m_desktopRes.bFullScreen  = true;
428       m_desktopRes.iWidth       = tv_state.display.hdmi.width;
429       m_desktopRes.iHeight      = tv_state.display.hdmi.height;
430       m_desktopRes.iScreenWidth = tv_state.display.hdmi.width;
431       m_desktopRes.iScreenHeight= tv_state.display.hdmi.height;
432       m_desktopRes.dwFlags      = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode);
433       m_desktopRes.fPixelRatio  = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
434       // Also add 3D flags
435       if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF)
436       {
437         m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
438         m_desktopRes.fPixelRatio *= 2.0;
439       }
440       else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF)
441       {
442         m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
443         m_desktopRes.fPixelRatio *= 0.5;
444       }
445       m_desktopRes.fRefreshRate = (float)tv_state.display.hdmi.frame_rate;
446     }
447     else // sdtv
448     {
449       m_desktopRes.iScreen      = 0;
450       m_desktopRes.bFullScreen  = true;
451       m_desktopRes.iWidth       = tv_state.display.sdtv.width;
452       m_desktopRes.iHeight      = tv_state.display.sdtv.height;
453       m_desktopRes.iScreenWidth = tv_state.display.sdtv.width;
454       m_desktopRes.iScreenHeight= tv_state.display.sdtv.height;
455       m_desktopRes.dwFlags      = D3DPRESENTFLAG_INTERLACED;
456       m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate;
457       m_desktopRes.fPixelRatio  = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
458     }
459
460     m_desktopRes.strMode = StringUtils::Format("%dx%d", m_desktopRes.iScreenWidth, m_desktopRes.iScreenHeight);
461
462     if((int)m_desktopRes.fRefreshRate > 1)
463       SetResolutionString(m_desktopRes);
464
465     m_initDesktopRes = false;
466
467     m_desktopRes.iSubtitles   = (int)(0.965 * m_desktopRes.iHeight);
468
469     CLog::Log(LOGDEBUG, "EGL initial desktop resolution %s (%.2f)\n", m_desktopRes.strMode.c_str(), m_desktopRes.fPixelRatio);
470   }
471
472   GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions);
473   GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions);
474
475   if(resolutions.size() == 0)
476   {
477     RESOLUTION_INFO res;
478     CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags);
479
480     AddUniqueResolution(m_desktopRes, resolutions);
481   }
482
483   if(resolutions.size() < 2)
484     m_fixedMode = true;
485
486   DLOG("CEGLNativeTypeRaspberryPI::ProbeResolutions\n");
487   return true;
488 #else
489   return false;
490 #endif
491 }
492
493 bool CEGLNativeTypeRaspberryPI::GetPreferredResolution(RESOLUTION_INFO *res) const
494 {
495   DLOG("CEGLNativeTypeRaspberryPI::GetPreferredResolution\n");
496   return false;
497 }
498
499 bool CEGLNativeTypeRaspberryPI::ShowWindow(bool show)
500 {
501   DLOG("CEGLNativeTypeRaspberryPI::ShowWindow\n");
502   return false;
503 }
504
505 #if defined(TARGET_RASPBERRY_PI)
506 void CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow()
507 {
508   if(!m_DllBcmHost)
509     return;
510
511   DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0);
512
513   if (m_dispman_element != DISPMANX_NO_HANDLE)
514   {
515     m_DllBcmHost->vc_dispmanx_element_remove(dispman_update, m_dispman_element);
516     m_dispman_element = DISPMANX_NO_HANDLE;
517   }
518   m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update);
519
520   if (m_dispman_display != DISPMANX_NO_HANDLE)
521   {
522     m_DllBcmHost->vc_dispmanx_display_close(m_dispman_display);
523     m_dispman_display = DISPMANX_NO_HANDLE;
524   }
525   DLOG("CEGLNativeTypeRaspberryPI::DestroyDispmaxWindow\n");
526 }
527
528 void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::vector<RESOLUTION_INFO> &resolutions)
529 {
530   if(!m_DllBcmHost)
531     return;
532
533   //Supported HDMI CEA/DMT resolutions, preferred resolution will be returned
534   int32_t num_modes = 0;
535   HDMI_RES_GROUP_T prefer_group;
536   uint32_t prefer_mode;
537   int i;
538   TV_SUPPORTED_MODE_NEW_T *supported_modes = NULL;
539   // query the number of modes first
540   int max_supported_modes = m_DllBcmHost->vc_tv_hdmi_get_supported_modes_new(group, NULL, 0, &prefer_group, &prefer_mode);
541
542   if (max_supported_modes > 0)
543     supported_modes = new TV_SUPPORTED_MODE_NEW_T[max_supported_modes];
544
545   if (supported_modes)
546   {
547     num_modes = m_DllBcmHost->vc_tv_hdmi_get_supported_modes_new(group,
548         supported_modes, max_supported_modes, &prefer_group, &prefer_mode);
549
550     CLog::Log(LOGDEBUG, "EGL get supported modes (%d) = %d, prefer_group=%x, prefer_mode=%x\n",
551         group, num_modes, prefer_group, prefer_mode);
552   }
553
554   if (num_modes > 0 && prefer_group != HDMI_RES_GROUP_INVALID)
555   {
556     TV_SUPPORTED_MODE_NEW_T *tv = supported_modes;
557     for (i=0; i < num_modes; i++, tv++)
558     {
559       RESOLUTION_INFO res;
560
561       res.iScreen       = 0;
562       res.bFullScreen   = true;
563       res.dwFlags       = MAKEFLAGS(group, tv->code, tv->scan_mode);
564       res.fRefreshRate  = (float)tv->frame_rate;
565       res.iWidth        = tv->width;
566       res.iHeight       = tv->height;
567       res.iScreenWidth  = tv->width;
568       res.iScreenHeight = tv->height;
569       res.fPixelRatio   = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res.iScreenWidth / (float)res.iScreenHeight);
570
571       SetResolutionString(res);
572
573       CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f) %s%s:%x\n", i, res.strMode.c_str(), res.fPixelRatio,
574           tv->native ? "N" : "", tv->scan_mode ? "I" : "", tv->code);
575
576       res.iSubtitles    = (int)(0.965 * res.iHeight);
577
578       AddUniqueResolution(res, resolutions);
579
580       // Also add 3D versions of modes
581       if (tv->struct_3d_mask & HDMI_3D_STRUCT_SIDE_BY_SIDE_HALF_HORIZONTAL)
582       {
583         RESOLUTION_INFO res2 = res;
584         res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
585         res2.fPixelRatio    = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
586         res2.fPixelRatio   *= 2.0f;
587         SetResolutionString(res2);
588         CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
589
590         res2.iSubtitles    = (int)(0.965 * res2.iHeight);
591
592         AddUniqueResolution(res2, resolutions);
593       }
594       if (tv->struct_3d_mask & HDMI_3D_STRUCT_TOP_AND_BOTTOM)
595       {
596         RESOLUTION_INFO res2 = res;
597         res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
598         res2.fPixelRatio    = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
599         res2.fPixelRatio   *= 0.5f;
600         SetResolutionString(res2);
601         CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
602
603         res2.iSubtitles    = (int)(0.965 * res2.iHeight);
604
605         AddUniqueResolution(res2, resolutions);
606       }
607     }
608   }
609   if (supported_modes)
610     delete [] supported_modes;
611 }
612
613 void CEGLNativeTypeRaspberryPI::TvServiceCallback(uint32_t reason, uint32_t param1, uint32_t param2)
614 {
615   CLog::Log(LOGDEBUG, "EGL tv_service_callback (%d,%d,%d)\n", reason, param1, param2);
616   switch(reason)
617   {
618   case VC_HDMI_UNPLUGGED:
619     break;
620   case VC_HDMI_STANDBY:
621     break;
622   case VC_SDTV_NTSC:
623   case VC_SDTV_PAL:
624   case VC_HDMI_HDMI:
625   case VC_HDMI_DVI:
626     //Signal we are ready now
627     sem_post(&m_tv_synced);
628     break;
629   default:
630      break;
631   }
632 }
633
634 void CEGLNativeTypeRaspberryPI::CallbackTvServiceCallback(void *userdata, uint32_t reason, uint32_t param1, uint32_t param2)
635 {
636    CEGLNativeTypeRaspberryPI *callback = static_cast<CEGLNativeTypeRaspberryPI*>(userdata);
637    callback->TvServiceCallback(reason, param1, param2);
638 }
639
640 #endif
641