bool CEGLNativeTypeRaspberryPI::DestroyNativeWindow() { #if defined(TARGET_RASPBERRY_PI) DestroyDispmaxWindow(); free(m_nativeWindow); m_nativeWindow = NULL; DLOG("CEGLNativeTypeRaspberryPI::DestroyNativeWindow\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 }
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 }