bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions)
{
#if defined(TARGET_RASPBERRY_PI)
  resolutions.clear();

  if(!m_DllBcmHost)
    return false;

  /* read initial desktop resolution before probe resolutions.
   * probing will replace the desktop resolution when it finds the same one.
   * we raplace it because probing will generate more detailed 
   * resolution flags we don't get with vc_tv_get_state.
   */

  if(m_initDesktopRes)
  {
    TV_DISPLAY_STATE_T tv_state;

    // get current display settings state
    memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T));
    m_DllBcmHost->vc_tv_get_display_state(&tv_state);

    if ((tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) != 0) // hdtv
    {
      m_desktopRes.iScreen      = 0;
      m_desktopRes.bFullScreen  = true;
      m_desktopRes.iWidth       = tv_state.display.hdmi.width;
      m_desktopRes.iHeight      = tv_state.display.hdmi.height;
      m_desktopRes.iScreenWidth = tv_state.display.hdmi.width;
      m_desktopRes.iScreenHeight= tv_state.display.hdmi.height;
      m_desktopRes.dwFlags      = MAKEFLAGS(tv_state.display.hdmi.group, tv_state.display.hdmi.mode, tv_state.display.hdmi.scan_mode);
      m_desktopRes.fPixelRatio  = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
      HDMI_PROPERTY_PARAM_T property;
      property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
      vc_tv_hdmi_get_property(&property);
      m_desktopRes.fRefreshRate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tv_state.display.hdmi.frame_rate * (1000.0f/1001.0f) : tv_state.display.hdmi.frame_rate;
    }
    else if ((tv_state.state & ( VC_SDTV_NTSC | VC_SDTV_PAL )) != 0) // sdtv
    {
      m_desktopRes.iScreen      = 0;
      m_desktopRes.bFullScreen  = true;
      m_desktopRes.iWidth       = tv_state.display.sdtv.width;
      m_desktopRes.iHeight      = tv_state.display.sdtv.height;
      m_desktopRes.iScreenWidth = tv_state.display.sdtv.width;
      m_desktopRes.iScreenHeight= tv_state.display.sdtv.height;
      m_desktopRes.dwFlags      = MAKEFLAGS(HDMI_RES_GROUP_INVALID, tv_state.display.sdtv.mode, 1);
      m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate;
      m_desktopRes.fPixelRatio  = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
    }
    else if ((tv_state.state & VC_LCD_ATTACHED_DEFAULT) != 0) // lcd
    {
      m_desktopRes.iScreen      = 0;
      m_desktopRes.bFullScreen  = true;
      m_desktopRes.iWidth       = tv_state.display.sdtv.width;
      m_desktopRes.iHeight      = tv_state.display.sdtv.height;
      m_desktopRes.iScreenWidth = tv_state.display.sdtv.width;
      m_desktopRes.iScreenHeight= tv_state.display.sdtv.height;
      m_desktopRes.dwFlags      = MAKEFLAGS(HDMI_RES_GROUP_INVALID, 0, 0);
      m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate;
      m_desktopRes.fPixelRatio  = tv_state.display.hdmi.display_options.aspect == 0 ? 1.0f : get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
    }

    SetResolutionString(m_desktopRes);

    m_initDesktopRes = false;

    m_desktopRes.iSubtitles   = (int)(0.965 * m_desktopRes.iHeight);

    CLog::Log(LOGDEBUG, "EGL initial desktop resolution %s (%.2f)\n", m_desktopRes.strMode.c_str(), m_desktopRes.fPixelRatio);
  }

  if(GETFLAGS_GROUP(m_desktopRes.dwFlags) && GETFLAGS_MODE(m_desktopRes.dwFlags))
  {
    GetSupportedModes(HDMI_RES_GROUP_DMT, resolutions);
    GetSupportedModes(HDMI_RES_GROUP_CEA, resolutions);
  }
  {
    AddUniqueResolution(m_desktopRes, resolutions, true);
    CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags);
  }

  DLOG("CEGLNativeTypeRaspberryPI::ProbeResolutions\n");
  return true;
#else
  return false;
#endif
}
bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res)
{
#if defined(TARGET_RASPBERRY_PI)
  if(!m_DllBcmHost || !m_nativeWindow)
    return false;

  while (proc_find("hello_video.bin") >= 0)
    Sleep(100);

  DestroyDispmaxWindow();

  RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
  if(GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags))
  {
    uint32_t mode3d = HDMI_3D_FORMAT_NONE;
    sem_init(&m_tv_synced, 0, 0);
    m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this);

    if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL || stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
    {
      /* inform TV of any 3D settings. Note this property just applies to next hdmi mode change, so no need to call for 2D modes */
      HDMI_PROPERTY_PARAM_T property;
      property.property = HDMI_PROPERTY_3D_STRUCTURE;
      if (CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOSCREEN_FRAMEPACKING) && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_SUPPORTMVC) && res.fRefreshRate <= 30.0f)
        property.param1 = HDMI_3D_FORMAT_FRAME_PACKING;
      else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
        property.param1 = HDMI_3D_FORMAT_SBS_HALF;
      else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
        property.param1 = HDMI_3D_FORMAT_TB_HALF;
      else
        property.param1 = HDMI_3D_FORMAT_NONE;
      property.param2 = 0;
      mode3d = property.param1;
      vc_tv_hdmi_set_property(&property);
    }

    HDMI_PROPERTY_PARAM_T property;
    property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
    // if we are closer to ntsc version of framerate, let gpu know
    int   iFrameRate  = (int)(res.fRefreshRate + 0.5f);
    if (fabsf(res.fRefreshRate * (1001.0f / 1000.0f) - iFrameRate) < fabsf(res.fRefreshRate - iFrameRate))
      property.param1 = HDMI_PIXEL_CLOCK_TYPE_NTSC;
    else
      property.param1 = HDMI_PIXEL_CLOCK_TYPE_PAL;
    property.param2 = 0;
    vc_tv_hdmi_set_property(&property);

    int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags));

    if (success == 0)
    {
      CLog::Log(LOGDEBUG, "EGL set HDMI mode (%d,%d)=%d %s%s\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
                          CStereoscopicsManager::GetInstance().ConvertGuiStereoModeToString(stereo_mode),
                          mode3d==HDMI_3D_FORMAT_FRAME_PACKING ? " FP" : mode3d==HDMI_3D_FORMAT_SBS_HALF ? " SBS" : mode3d==HDMI_3D_FORMAT_TB_HALF ? " TB" : "");

      sem_wait(&m_tv_synced);
    }
    else
    {
      CLog::Log(LOGERROR, "EGL failed to set HDMI mode (%d,%d)=%d %s%s\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
                          CStereoscopicsManager::GetInstance().ConvertGuiStereoModeToString(stereo_mode),
                          mode3d==HDMI_3D_FORMAT_FRAME_PACKING ? " FP" : mode3d==HDMI_3D_FORMAT_SBS_HALF ? " SBS" : mode3d==HDMI_3D_FORMAT_TB_HALF ? " TB" : "");
    }
    m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback);
    sem_destroy(&m_tv_synced);

    m_desktopRes = res;
  }
  else if(!GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags))
  {
    sem_init(&m_tv_synced, 0, 0);
    m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this);

    SDTV_OPTIONS_T options;
    options.aspect = get_sdtv_aspect_from_display_aspect((float)res.iScreenWidth / (float)res.iScreenHeight);

    int success = m_DllBcmHost->vc_tv_sdtv_power_on((SDTV_MODE_T)GETFLAGS_MODE(res.dwFlags), &options);

    if (success == 0)
    {
      CLog::Log(LOGDEBUG, "EGL set SDTV mode (%d,%d)=%d\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success);

      sem_wait(&m_tv_synced);
    }
    else
    {
      CLog::Log(LOGERROR, "EGL failed to set SDTV mode (%d,%d)=%d\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success);
    }
    m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback);
    sem_destroy(&m_tv_synced);

    m_desktopRes = res;
  }

  m_dispman_display = g_RBP.OpenDisplay(0);

  m_width   = res.iWidth;
  m_height  = res.iHeight;

  VC_RECT_T dst_rect;
  VC_RECT_T src_rect;

  dst_rect.x      = 0;
  dst_rect.y      = 0;
  dst_rect.width  = res.iScreenWidth;
  dst_rect.height = res.iScreenHeight;

  src_rect.x      = 0;
  src_rect.y      = 0;
  src_rect.width  = m_width << 16;
  src_rect.height = m_height << 16;

  VC_DISPMANX_ALPHA_T alpha;
  memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
  alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;

  DISPMANX_CLAMP_T clamp;
  memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T));

  DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE;
  DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0);

  if (stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
    transform = DISPMANX_STEREOSCOPIC_SBS;
  else if (stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
    transform = DISPMANX_STEREOSCOPIC_TB;
  else
    transform = DISPMANX_STEREOSCOPIC_MONO;

  CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps (%d,%d) flags:%x aspect:%.2f\n",
      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);

  m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
    m_dispman_display,
    1,                              // layer
    &dst_rect,
    (DISPMANX_RESOURCE_HANDLE_T)0,  // src
    &src_rect,
    DISPMANX_PROTECTION_NONE,
    &alpha,                         //alphe
    &clamp,                         //clamp
    transform);                     // transform

  assert(m_dispman_element != DISPMANX_NO_HANDLE);
  assert(m_dispman_element != (unsigned)DISPMANX_INVALID);

  memset(m_nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T));

  EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow;

  nativeWindow->element = m_dispman_element;
  nativeWindow->width   = m_width;
  nativeWindow->height  = m_height;

  m_DllBcmHost->vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00);
  m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update);

  DLOG("CEGLNativeTypeRaspberryPI::SetNativeResolution\n");

  return true;
#else
  return false;
#endif
}
Exemple #3
0
bool CWinEGLPlatformRaspberryPI::SetDisplayResolution(RESOLUTION_INFO& res)
{
  EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow;

  DestroyWindow();

  bool bFound = false;

  RESOLUTION_INFO resSearch;

  int best_score = 0;

  for (size_t i = 0; i < m_res.size(); i++)
  {
    if(m_res[i].iWidth == res.iWidth && m_res[i].iHeight == res.iHeight && m_res[i].fRefreshRate == res.fRefreshRate)
    {
      int score = 0;

      /* prefere progressive over interlaced */
      if(!GETFLAGS_INTERLACE(m_res[i].dwFlags))
        score = 1;

      if(score >= best_score)
      {
        resSearch = m_res[i];
        bFound = true;
      }
    }
  }

  if(bFound)
  {
    sem_init(&m_tv_synced, 0, 0);
    m_DllBcmHost.vc_tv_register_callback(CallbackTvServiceCallback, this);
  
    int success = m_DllBcmHost.vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), GETFLAGS_MODE(resSearch.dwFlags));

    if (success == 0) 
    {
      CLog::Log(LOGINFO, "CWinEGLPlatformRaspberryPI::SetDisplayResolution set HDMI mode (%d,%d,%d)=%d\n", 
                          GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), 
                          GETFLAGS_MODE(resSearch.dwFlags), success);
      sem_wait(&m_tv_synced);
    } 
    else 
    {
      CLog::Log(LOGERROR, "CWinEGLPlatformRaspberryPI::SetDisplayResolution failed to set HDMI mode (%d,%d,%d)=%d\n", 
                          GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), 
                          GETFLAGS_MODE(resSearch.dwFlags), success);
    }
    m_DllBcmHost.vc_tv_unregister_callback(CallbackTvServiceCallback);
    sem_destroy(&m_tv_synced);
  }

  m_dispman_display = m_DllBcmHostDisplay.vc_dispmanx_display_open(0);

  OVERSCAN &overscan = res.Overscan;

  m_width   = res.iWidth;
  m_height  = res.iHeight;
  //m_bFullScreen = fullScreen;
  m_fb_width  = res.iWidth;
  m_fb_height = res.iHeight;

  m_fb_bpp    = 8;

  VC_RECT_T dst_rect;
  VC_RECT_T src_rect;

  dst_rect.x = overscan.left;
  dst_rect.y = overscan.top;
  dst_rect.width = overscan.right-overscan.left;
  dst_rect.height = overscan.bottom-overscan.top;

  src_rect.x = 0;
  src_rect.y = 0;
  src_rect.width = m_fb_width << 16;
  src_rect.height = m_fb_height << 16;

  VC_DISPMANX_ALPHA_T alpha;
  memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
  alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;

  DISPMANX_CLAMP_T clamp;
  memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T));

  DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE;
  DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHostDisplay.vc_dispmanx_update_start(0);
  CLog::Log(LOGDEBUG, "CWinEGLPlatformRaspberryPI::SetDisplayResolution %dx%d->%dx%d\n", m_fb_width, m_fb_height, dst_rect.width, dst_rect.height);

  // width < height => half SBS
  if (src_rect.width < src_rect.height)
  {
    // right side
    /*
    dst_rect.x = m_width;
    dst_rect.width = m_width;
    */
    dst_rect.x = res.iWidth;
    dst_rect.width >>= overscan.right - dst_rect.x;
    m_dispman_element2 = m_DllBcmHostDisplay.vc_dispmanx_element_add(dispman_update,
      m_dispman_display,
      1,                              // layer
      &dst_rect,
      (DISPMANX_RESOURCE_HANDLE_T)0,  // src
      &src_rect,
      DISPMANX_PROTECTION_NONE,
      //(VC_DISPMANX_ALPHA_T*)0,        // alpha
      &alpha,
      //(DISPMANX_CLAMP_T*)0,           // clamp
      &clamp,
      //(DISPMANX_TRANSFORM_T)0);       // transform
      transform);       // transform
      assert(m_dispman_element2 != DISPMANX_NO_HANDLE);
      assert(m_dispman_element2 != (unsigned)DISPMANX_INVALID);
    // left side - fall through
    /*
    dst_rect.x = 0;
    dst_rect.width = m_width;
    */
    dst_rect.x = overscan.left;
    dst_rect.width = res.iWidth - dst_rect.x;
  }
bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res)
{
#if defined(TARGET_RASPBERRY_PI)
  if(!m_DllBcmHost || !m_nativeWindow)
    return false;

  DestroyDispmaxWindow();

  if(!m_fixedMode && GETFLAGS_GROUP(res.dwFlags) && GETFLAGS_MODE(res.dwFlags))
  {
    sem_init(&m_tv_synced, 0, 0);
    m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this);

    if (res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))
    {
      /* inform TV of any 3D settings. Note this property just applies to next hdmi mode change, so no need to call for 2D modes */
      HDMI_PROPERTY_PARAM_T property;
      property.property = HDMI_PROPERTY_3D_STRUCTURE;
      if (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
        property.param1 = HDMI_3D_FORMAT_SBS_HALF;
      else if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB)
        property.param1 = HDMI_3D_FORMAT_TB_HALF;
      else
        property.param1 = HDMI_3D_FORMAT_NONE;
      property.param2 = 0;
      vc_tv_hdmi_set_property(&property);
    }
    int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags));

    if (success == 0)
    {
      CLog::Log(LOGDEBUG, "EGL set HDMI mode (%d,%d)=%d%s%s\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
                          (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? " SBS":"",
                          (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? " TB":"");

      sem_wait(&m_tv_synced);
    }
    else
    {
      CLog::Log(LOGERROR, "EGL failed to set HDMI mode (%d,%d)=%d%s%s\n",
                          GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags), success,
                          (res.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? " SBS":"",
                          (res.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? " TB":"");
    }
    m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback);
    sem_destroy(&m_tv_synced);

    m_desktopRes = res;
  }

  m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0);

  m_width   = res.iWidth;
  m_height  = res.iHeight;

  VC_RECT_T dst_rect;
  VC_RECT_T src_rect;

  dst_rect.x      = 0;
  dst_rect.y      = 0;
  dst_rect.width  = res.iScreenWidth;
  dst_rect.height = res.iScreenHeight;

  src_rect.x      = 0;
  src_rect.y      = 0;
  src_rect.width  = m_width << 16;
  src_rect.height = m_height << 16;

  VC_DISPMANX_ALPHA_T alpha;
  memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
  alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;

  DISPMANX_CLAMP_T clamp;
  memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T));

  DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE;
  DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0);

  CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps (%d,%d) flags:%x aspect:%.2f\n",
      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);

  // The trick for SBS is that we stick two dispman elements together 
  // and the PI firmware knows that we are in SBS/TAB mode and it renders the gui in SBS/TAB
  if(res.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB))
  {
    if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB)
    {
      // bottom half
      dst_rect.y = res.iScreenHeight;
    }
    else
    {
      // right side
      dst_rect.x = res.iScreenWidth;
    }

    m_dispman_element2 = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
      m_dispman_display,
      1,                              // layer
      &dst_rect,
      (DISPMANX_RESOURCE_HANDLE_T)0,  // src
      &src_rect,
      DISPMANX_PROTECTION_NONE,
      &alpha,                         // alpha
      &clamp,                         // clamp
      transform);                     // transform
      assert(m_dispman_element2 != DISPMANX_NO_HANDLE);
      assert(m_dispman_element2 != (unsigned)DISPMANX_INVALID);

    if (res.dwFlags & D3DPRESENTFLAG_MODE3DTB)
    {
      // top half - fall through
      dst_rect.y = 0;
    }
    else
    {
      // left side - fall through
      dst_rect.x = 0;
    }
  }

  m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
    m_dispman_display,
    1,                              // layer
    &dst_rect,
    (DISPMANX_RESOURCE_HANDLE_T)0,  // src
    &src_rect,
    DISPMANX_PROTECTION_NONE,
    &alpha,                         //alphe
    &clamp,                         //clamp
    transform);                     // transform

  assert(m_dispman_element != DISPMANX_NO_HANDLE);
  assert(m_dispman_element != (unsigned)DISPMANX_INVALID);

  memset(m_nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T));

  EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow;

  nativeWindow->element = m_dispman_element;
  nativeWindow->width   = m_width;
  nativeWindow->height  = m_height;

  m_DllBcmHost->vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00);
  m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update);

  DLOG("CEGLNativeTypeRaspberryPI::SetNativeResolution\n");

  return true;
#else
  return false;
#endif
}
bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res)
{
#if defined(TARGET_RASPBERRY_PI)
  bool bFound = false;

  if(!m_DllBcmHost || !m_nativeWindow)
    return false;

  DestroyDispmaxWindow();

  RESOLUTION_INFO resSearch;

  int best_score = 0;

  for (size_t i = 0; i < m_res.size(); i++)
  {
    if(m_res[i].iScreenWidth == res.iScreenWidth && m_res[i].iScreenHeight == res.iScreenHeight && m_res[i].fRefreshRate == res.fRefreshRate)
    {
      int score = 0;

      /* prefere progressive over interlaced */
      if(!GETFLAGS_INTERLACE(m_res[i].dwFlags))
        score = 1;

      if(score >= best_score)
      {
        resSearch = m_res[i];
        bFound = true;
      }
    }
  }

  if(bFound && !m_fixedMode)
  {
    sem_init(&m_tv_synced, 0, 0);
    m_DllBcmHost->vc_tv_register_callback(CallbackTvServiceCallback, this);

    int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit(HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags), GETFLAGS_MODE(resSearch.dwFlags));

    if (success == 0)
    {
      CLog::Log(LOGDEBUG, "EGL set HDMI mode (%d,%d,%d)=%d\n",
                          GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags),
                          GETFLAGS_MODE(resSearch.dwFlags), success);
      sem_wait(&m_tv_synced);
    }
    else
    {
      CLog::Log(LOGERROR, "EGL failed to set HDMI mode (%d,%d,%d)=%d\n",
                          GETFLAGS_MODE3D(resSearch.dwFlags) ? HDMI_MODE_3D:HDMI_MODE_HDMI, GETFLAGS_GROUP(resSearch.dwFlags),
                          GETFLAGS_MODE(resSearch.dwFlags), success);
    }
    m_DllBcmHost->vc_tv_unregister_callback(CallbackTvServiceCallback);
    sem_destroy(&m_tv_synced);

    m_desktopRes = resSearch;
  }

  m_dispman_display = m_DllBcmHost->vc_dispmanx_display_open(0);

  m_width   = res.iWidth;
  m_height  = res.iHeight;

  VC_RECT_T dst_rect;
  VC_RECT_T src_rect;

  dst_rect.x      = 0;
  dst_rect.y      = 0;
  dst_rect.width  = res.iScreenWidth;
  dst_rect.height = res.iScreenHeight;

  src_rect.x      = 0;
  src_rect.y      = 0;
  src_rect.width  = m_width << 16;
  src_rect.height = m_height << 16;

  VC_DISPMANX_ALPHA_T alpha;
  memset(&alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
  alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE;

  DISPMANX_CLAMP_T clamp;
  memset(&clamp, 0x0, sizeof(DISPMANX_CLAMP_T));

  DISPMANX_TRANSFORM_T transform = DISPMANX_NO_ROTATE;
  DISPMANX_UPDATE_HANDLE_T dispman_update = m_DllBcmHost->vc_dispmanx_update_start(0);

  CLog::Log(LOGDEBUG, "EGL set resolution %dx%d -> %dx%d @ %.2f fps\n",
      m_width, m_height, dst_rect.width, dst_rect.height, bFound ? resSearch.fRefreshRate : res.fRefreshRate);

  // The trick for SBS is that we stick two dispman elements together 
  // and the PI firmware knows that we are in SBS mode and it renders the gui in SBS
  if(bFound && (resSearch.dwFlags & D3DPRESENTFLAG_MODE3DSBS))
  {
    // right side
    dst_rect.x = res.iScreenWidth;
    dst_rect.width = res.iScreenWidth;

    m_dispman_element2 = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
      m_dispman_display,
      1,                              // layer
      &dst_rect,
      (DISPMANX_RESOURCE_HANDLE_T)0,  // src
      &src_rect,
      DISPMANX_PROTECTION_NONE,
      &alpha,                         // alpha
      &clamp,                         // clamp
      transform);                     // transform
      assert(m_dispman_element2 != DISPMANX_NO_HANDLE);
      assert(m_dispman_element2 != (unsigned)DISPMANX_INVALID);

    // left side - fall through
    dst_rect.x = 0;
    dst_rect.width = res.iScreenWidth;
  }

  m_dispman_element = m_DllBcmHost->vc_dispmanx_element_add(dispman_update,
    m_dispman_display,
    1,                              // layer
    &dst_rect,
    (DISPMANX_RESOURCE_HANDLE_T)0,  // src
    &src_rect,
    DISPMANX_PROTECTION_NONE,
    &alpha,                         //alphe
    &clamp,                         //clamp
    transform);                     // transform

  assert(m_dispman_element != DISPMANX_NO_HANDLE);
  assert(m_dispman_element != (unsigned)DISPMANX_INVALID);

  memset(m_nativeWindow, 0, sizeof(EGL_DISPMANX_WINDOW_T));

  EGL_DISPMANX_WINDOW_T *nativeWindow = (EGL_DISPMANX_WINDOW_T *)m_nativeWindow;

  nativeWindow->element = m_dispman_element;
  nativeWindow->width   = m_width;
  nativeWindow->height  = m_height;

  m_DllBcmHost->vc_dispmanx_display_set_background(dispman_update, m_dispman_display, 0x00, 0x00, 0x00);
  m_DllBcmHost->vc_dispmanx_update_submit_sync(dispman_update);

  DLOG("CEGLNativeTypeRaspberryPI::SetNativeResolution\n");

  return true;
#else
  return false;
#endif
}