From 9c17370c706e91c22b63e9c0a917c2463c23a091 Mon Sep 17 00:00:00 2001 From: Rabeeh Khoury Date: Tue, 15 Jan 2013 16:27:29 +0200 Subject: [PATCH] Use Dove hardware graphics scaler The theory behind this patch is to render to a smaller area and then use the hardware upscaler to upscale the graphics plane to the destination resolution. For instance, going into system setting->system->Video output and choosing Graphics scaling to 1.5, will make 1080p resolution to rendering 1/1.5 of it's size (720p). Rendering becomes much more faster, memory bandwidth on the LCD controller becomes half too. Using this patch it's now possible to get higher fps on XBMC GUI Signed-off-by: Rabeeh Khoury --- xbmc/cores/VideoRenderers/DoveOverlayRenderer.cpp | 13 ++++-- xbmc/guilib/GraphicContext.cpp | 14 +++++++ xbmc/guilib/Resolution.h | 7 ++++ xbmc/settings/GUISettings.cpp | 7 ++++ xbmc/settings/GUIWindowSettingsCategory.cpp | 5 +++ xbmc/video/windows/GUIWindowFullScreen.cpp | 17 ++++++++ xbmc/windowing/X11/XRandR.cpp | 45 +++++++++++++++++++++ xbmc/windowing/X11/XRandR.h | 3 ++ 8 files changed, 107 insertions(+), 4 deletions(-) diff --git a/xbmc/cores/VideoRenderers/DoveOverlayRenderer.cpp b/xbmc/cores/VideoRenderers/DoveOverlayRenderer.cpp index be37ab5..72343ca 100644 --- a/xbmc/cores/VideoRenderers/DoveOverlayRenderer.cpp +++ b/xbmc/cores/VideoRenderers/DoveOverlayRenderer.cpp @@ -205,11 +205,16 @@ bool CDoveOverlayRenderer::Configure( return false; } - int interpolation = 3; // bi-linear interpolation - if (ioctl(m_overlayfd, DOVEFB_IOCTL_SET_INTERPOLATION_MODE, &interpolation) != 0) + GRAPHICS_SCALING scale = (GRAPHICS_SCALING) g_guiSettings.GetInt("videoscreen.graphics_scaling"); + if (scale == -1) scale=GR_SCALE_100; + if (scale == GR_SCALE_100) /* Scaler is set differently when using graphics scaler */ { - CLog::Log(LOGERROR, "%s::%s - Failed to setup video interpolation mode", CLASSNAME, __func__); - return false; + int interpolation = 3; // bi-linear interpolation + if (ioctl(m_overlayfd, DOVEFB_IOCTL_SET_INTERPOLATION_MODE, &interpolation) != 0) + { + CLog::Log(LOGERROR, "%s::%s - Failed to setup video interpolation mode", CLASSNAME, __func__); + return false; + } } struct _sColorKeyNAlpha alpha; diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp index 94f248b..e5edfcd 100644 --- a/xbmc/guilib/GraphicContext.cpp +++ b/xbmc/guilib/GraphicContext.cpp @@ -626,6 +626,19 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need float fToWidth; float fToHeight; +#ifdef HAS_MARVELL_DOVE + GRAPHICS_SCALING scale = (GRAPHICS_SCALING) g_guiSettings.GetInt("videoscreen.graphics_scaling"); + if (scale == -1) /* not configured */ + scale = GR_SCALE_100; + { + fFromWidth = (float)res.iWidth; + fFromHeight = (float)res.iHeight; + fToPosX = (float)g_settings.m_ResInfo[m_Resolution].Overscan.left*100/scale; + fToPosY = (float)g_settings.m_ResInfo[m_Resolution].Overscan.top*100/scale; + fToWidth = (float)g_settings.m_ResInfo[m_Resolution].Overscan.right*100/scale - fToPosX; + fToHeight = (float)g_settings.m_ResInfo[m_Resolution].Overscan.bottom*100/scale - fToPosY; + } +#else { fFromWidth = (float)res.iWidth; fFromHeight = (float)res.iHeight; @@ -634,6 +647,7 @@ void CGraphicContext::SetScalingResolution(const RESOLUTION_INFO &res, bool need fToWidth = (float)g_settings.m_ResInfo[m_Resolution].Overscan.right - fToPosX; fToHeight = (float)g_settings.m_ResInfo[m_Resolution].Overscan.bottom - fToPosY; } +#endif if(!g_guiSkinzoom) // lookup gui setting if we didn't have it already g_guiSkinzoom = (CSettingInt*)g_guiSettings.GetSetting("lookandfeel.skinzoom"); diff --git a/xbmc/guilib/Resolution.h b/xbmc/guilib/Resolution.h index 66c4e85..a9b7d6c 100644 --- a/xbmc/guilib/Resolution.h +++ b/xbmc/guilib/Resolution.h @@ -63,6 +63,15 @@ VSYNC_DRIVER = 3 }; +#ifdef TARGET_MARVELL_DOVE +enum GRAPHICS_SCALING { + GR_SCALE_100 = 100, + GR_SCALE_150 = 150, + GR_SCALE_200 = 200, + GR_SCALE_250 = 250 +}; +#endif + struct OVERSCAN { int left; diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index bb39c86..6f0ba5e 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -435,6 +435,15 @@ AddSeparator(vs, "videoscreen.sep1"); #endif +#ifdef TARGET_MARVELL_DOVE + map graphics_scaling; + graphics_scaling.insert(make_pair(37011,GR_SCALE_100)); + graphics_scaling.insert(make_pair(37012,GR_SCALE_150)); + graphics_scaling.insert(make_pair(37013,GR_SCALE_200)); + graphics_scaling.insert(make_pair(37014,GR_SCALE_250)); + AddInt(vs, "videoscreen.graphics_scaling", 37010, GR_SCALE_100, graphics_scaling, SPIN_CONTROL_TEXT); +#endif + map vsync; #if defined(_LINUX) && !defined(TARGET_DARWIN) vsync.insert(make_pair(13101,VSYNC_DRIVER)); diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index d98107f..0ae1822 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -1490,6 +1490,11 @@ void CGUIWindowSettingsCategory::OnSettingChanged(BaseSettingControlPtr pSetting CLog::Log(LOGERROR, "Unable to open vmeta clock settings file on sysfs"); fclose(Fh); } + else if (strSetting.Equals("videoscreen.graphics_scaling")) + { + /* Fake as resolution changed - this to refresh aspect ratios of fonts vs. graphics */ + g_graphicsContext.SetVideoResolution(g_graphicsContext.GetVideoResolution(), true); + } #endif else if (strSetting.Equals("videoscreen.vsync")) { diff --git a/xbmc/video/windows/GUIWindowFullScreen.cpp b/xbmc/video/windows/GUIWindowFullScreen.cpp index 7b80926..24e2d98 100644 --- a/xbmc/video/windows/GUIWindowFullScreen.cpp +++ b/xbmc/video/windows/GUIWindowFullScreen.cpp @@ -1082,6 +1082,11 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() CStdString subtitleText = "How now brown cow"; if (g_application.m_pPlayer->GetCurrentSubtitle(subtitleText)) { +#ifdef HAS_MARVELL_DOVE + GRAPHICS_SCALING scale = (GRAPHICS_SCALING) g_guiSettings.GetInt("videoscreen.graphics_scaling"); + if (scale == -1) /* not configured */ + scale = GR_SCALE_100; +#endif // Remove HTML-like tags from the subtitles until subtitleText.Replace("\\r", ""); subtitleText.Replace("\r", ""); @@ -1105,7 +1110,11 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() RESOLUTION res = g_graphicsContext.GetVideoResolution(); g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetResInfo(), false); +#ifdef HAS_MARVELL_DOVE + float maxWidth = (float) g_settings.m_ResInfo[res].Overscan.right*100/scale - g_settings.m_ResInfo[res].Overscan.left; +#else float maxWidth = (float) g_settings.m_ResInfo[res].Overscan.right - g_settings.m_ResInfo[res].Overscan.left; +#endif m_subsLayout->Update(subtitleText, maxWidth * 0.9f, false, true); // true to force LTR reading order (most Hebrew subs are this format) int subalign = g_guiSettings.GetInt("subtitles.align"); @@ -1115,7 +1124,11 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() float y = (float) g_settings.m_ResInfo[res].iSubtitles; if (subalign == SUBTITLE_ALIGN_MANUAL) +#ifdef HAS_MARVELL_DOVE + y = (float) g_settings.m_ResInfo[res].iSubtitles*100/scale - textHeight; +#else y = (float) g_settings.m_ResInfo[res].iSubtitles - textHeight; +#endif else { CRect SrcRect, DestRect; @@ -1133,7 +1146,11 @@ void CGUIWindowFullScreen::RenderTTFSubtitles() y += g_graphicsContext.GetHeight() - g_settings.m_ResInfo[res].iSubtitles; y = std::max(y, (float) g_settings.m_ResInfo[res].Overscan.top); +#ifdef HAS_MARVELL_DOVE + y = std::min(y, g_settings.m_ResInfo[res].Overscan.bottom*100/scale - textHeight); +#else y = std::min(y, g_settings.m_ResInfo[res].Overscan.bottom - textHeight); +#endif } m_subsLayout->RenderOutline(x, y, 0, 0xFF000000, XBFONT_CENTER_X, maxWidth); diff --git a/xbmc/windowing/X11/XRandR.cpp b/xbmc/windowing/X11/XRandR.cpp index d8e9161..d23b76e 100644 --- a/xbmc/windowing/X11/XRandR.cpp +++ b/xbmc/windowing/X11/XRandR.cpp @@ -26,6 +26,11 @@ #include #include "system.h" #include "PlatformInclude.h" +#ifdef TARGET_MARVELL_DOVE +#include +#include "guilib/Resolution.h" +#include "settings/GUISettings.h" +#endif #include "utils/XBMCTinyXML.h" #include "../xbmc/utils/log.h" @@ -158,8 +163,44 @@ void CXRandR::RestoreState() } } +#ifdef TARGET_MARVELL_DOVE +#define MAP_SIZE 4096UL +#define MAP_MASK (MAP_SIZE - 1) +void CXRandR::ChangeGraphicsScaler(void) +{ + /* OK. Now this is a seriously ugly hack. Code needs to be re-written to support ioctl to driver !!! */ + /* Code below originally from devmem2.c */ + int fd; + off_t target_page = 0xf1820000; /* LCD Controller base address */ + void *map_base; + unsigned int zoomed; + unsigned int gr_size; + int zx,zy; + GRAPHICS_SCALING scale = (GRAPHICS_SCALING) g_guiSettings.GetInt("videoscreen.graphics_scaling"); + if (scale == -1) scale=GR_SCALE_100; + if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { + CLog::Log(LOGERROR, "XRANDR: Unable to open /dev/mem"); + return; + } + fflush(stdout); + map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target_page); + zoomed = * (unsigned int *) (map_base + 0x108); + zx = zoomed & 0xffff; + zy = (zoomed & 0xffff0000) >> 16; + CLog::Log(LOGINFO, "XRANDR: Zoomed area is %dx%d, new area should be %dx%d\n",zx,zy,zx*100/scale,zy*100/scale); + gr_size = (zy*100/scale) & 0xffff; + gr_size = (gr_size << 16) | ((zx*100/scale) & 0xffff); + * (unsigned int *) (map_base + 0x104) = gr_size; + close(fd); +} +#endif + bool CXRandR::SetMode(XOutput output, XMode mode) { +#ifdef TARGET_MARVELL_DOVE + /* Required both on entrance and exit from SetMode. First entrance is required to get the scaler modified */ + ChangeGraphicsScaler (); +#endif if ((output.name == m_currentOutput && mode.id == m_currentMode) || (output.name == "" && mode.id == "")) return true; @@ -256,6 +298,9 @@ bool CXRandR::SetMode(XOutput output, XMode mode) if (WEXITSTATUS(status) != 0) return false; +#ifdef TARGET_MARVELL_DOVE + ChangeGraphicsScaler (); +#endif return true; } diff --git a/xbmc/windowing/X11/XRandR.h b/xbmc/windowing/X11/XRandR.h index 2a269d0..95e4a1f 100644 --- a/xbmc/windowing/X11/XRandR.h +++ b/xbmc/windowing/X11/XRandR.h @@ -100,6 +100,9 @@ public: void LoadCustomModeLinesToAllOutputs(void); void SaveState(); void RestoreState(); +#ifdef TARGET_MARVELL_DOVE + void ChangeGraphicsScaler(void); +#endif //bool Has1080i(); //bool Has1080p(); //bool Has720p(); diff --git a/language/English/strings.po b/language/English/strings.po index fcb9255..8f36605 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -11420,3 +11420,23 @@ msgctxt "#36041" msgid "* Item folder" msgstr "" + +msgctxt "#37010" +msgid "Graphics Scaling" +msgstr "" + +msgctxt "#37011" +msgid "x1" +msgstr "" + +msgctxt "#37012" +msgid "x1.5" +msgstr "" + +msgctxt "#37013" +msgid "x2" +msgstr "" + +msgctxt "#37014" +msgid "x2.5" +msgstr ""