/*
* Copyright (C) 2013 Team XBMC
- * http://www.xbmc.org
+ * http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "guilib/GraphicContext.h"
#include "guilib/gui3d.h"
#include "guilib/LocalizeStrings.h"
+#include "guilib/StereoscopicsManager.h"
#include "settings/AdvancedSettings.h"
-#include "settings/Setting.h"
+#include "settings/lib/Setting.h"
#include "settings/Settings.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
return std::max(yonx, xony);
}
+static CStdString ModeFlagsToString(unsigned int flags, bool identifier)
+{
+ CStdString res;
+ if(flags & D3DPRESENTFLAG_INTERLACED)
+ res += "i";
+ else
+ res += "p";
+
+ if(!identifier)
+ res += " ";
+
+ if(flags & D3DPRESENTFLAG_MODE3DSBS)
+ res += "sbs";
+ else if(flags & D3DPRESENTFLAG_MODE3DTB)
+ res += "tab";
+ else if(identifier)
+ res += "std";
+ return res;
+}
+
CDisplaySettings::CDisplaySettings()
{
m_resolutions.insert(m_resolutions.begin(), RES_CUSTOM, RESOLUTION_INFO());
if (settingId == "videoscreen.resolution")
newRes = (RESOLUTION)((CSettingInt*)setting)->GetValue();
else if (settingId == "videoscreen.screen")
+ {
+ int screen = ((CSettingInt*)setting)->GetValue();
+
+ // if triggered by a change of screenmode, screen may not have changed
+ if (screen == GetCurrentDisplayMode())
+ return true;
+
+ // get desktop resolution for screen
newRes = GetResolutionForScreen();
+ }
string screenmode = GetStringFromResolution(newRes);
CSettings::Get().SetString("videoscreen.screenmode", screenmode);
// check if the old or the new resolution was/is windowed
// in which case we don't show any prompt to the user
- if (oldRes != RES_WINDOW && newRes != RES_WINDOW)
+ if (oldRes != RES_WINDOW && newRes != RES_WINDOW && oldRes != newRes)
{
if (!m_resolutionChangeAborted)
{
std::string screenmode = screenmodeSetting->GetValue();
// in Eden there was no character ("i" or "p") indicating interlaced/progressive
// at the end so we just add a "p" and assume progressive
+ // no 3d mode existed before, so just assume std modes
if (screenmode.size() == 20)
- return screenmodeSetting->SetValue(screenmode + "p");
+ return screenmodeSetting->SetValue(screenmode + "pstd");
+ if (screenmode.size() == 21)
+ return screenmodeSetting->SetValue(screenmode + "std");
+ }
+ else if (settingId == "videoscreen.vsync")
+ {
+ // This ifdef is intended to catch everything except Linux and FreeBSD
+#if !defined(TARGET_LINUX) || defined(TARGET_DARWIN) || defined(TARGET_ANDROID) || defined(TARGET_RASPBERRY_PI)
+ // in the Gotham alphas through beta3 the default value for darwin and android was set incorrectly.
+ CSettingInt *vsyncSetting = (CSettingInt*)setting;
+ if (vsyncSetting->GetValue() == VSYNC_DRIVER)
+ return vsyncSetting->SetValue(VSYNC_ALWAYS);
+#endif
}
return false;
void CDisplaySettings::AddResolutionInfo(const RESOLUTION_INFO &resolution)
{
CSingleLock lock(m_critical);
- m_resolutions.push_back(resolution);
+ RESOLUTION_INFO res(resolution);
+
+ if((res.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
+ {
+ /* add corrections for some special case modes frame packing modes */
+
+ if(res.iScreenWidth == 1920
+ && res.iScreenHeight == 2205)
+ {
+ res.iBlanking = 45;
+ res.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+ }
+
+ if(res.iScreenWidth == 1280
+ && res.iScreenHeight == 1470)
+ {
+ res.iBlanking = 30;
+ res.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+ }
+ }
+ m_resolutions.push_back(res);
}
void CDisplaySettings::ApplyCalibrations()
return GetCurrentResolutionInfo().iScreen;
}
-RESOLUTION CDisplaySettings::FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, bool interlaced)
+RESOLUTION CDisplaySettings::FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, unsigned flags)
{
- int interlace = interlaced ? 100 : 200;
-
// find the closest match to these in our res vector. If we have the screen, we score the res
RESOLUTION bestRes = RES_DESKTOP;
float bestScore = FLT_MAX;
+ flags &= D3DPRESENTFLAG_MODEMASK;
for (std::map<RESOLUTION, RESOLUTION_INFO>::const_iterator it = resolutionInfos.begin(); it != resolutionInfos.end(); ++it)
{
const RESOLUTION_INFO &info = it->second;
- if (info.iScreen != screen)
+
+ if ( info.iScreen != screen
+ || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != flags)
continue;
+
float score = 10 * (square_error((float)info.iScreenWidth, (float)width) +
square_error((float)info.iScreenHeight, (float)height) +
- square_error(info.fRefreshRate, refreshrate) +
- square_error((float)((info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? 100 : 200), (float)interlace));
+ square_error(info.fRefreshRate, refreshrate));
if (score < bestScore)
{
bestScore = score;
return RES_DESKTOP;
else if (strResolution == "WINDOW")
return RES_WINDOW;
- else if (strResolution.size() == 21)
+ else if (strResolution.size() >= 21)
{
- // format: SWWWWWHHHHHRRR.RRRRRP, where S = screen, W = width, H = height, R = refresh, P = interlace
+ // format: SWWWWWHHHHHRRR.RRRRRP333, where S = screen, W = width, H = height, R = refresh, P = interlace, 3 = stereo mode
int screen = strtol(StringUtils::Mid(strResolution, 0,1).c_str(), NULL, 10);
int width = strtol(StringUtils::Mid(strResolution, 1,5).c_str(), NULL, 10);
int height = strtol(StringUtils::Mid(strResolution, 6,5).c_str(), NULL, 10);
float refresh = (float)strtod(StringUtils::Mid(strResolution, 11,9).c_str(), NULL);
+ unsigned flags = 0;
+
// look for 'i' and treat everything else as progressive,
- // and use 100/200 to get a nice square_error.
- bool interlaced = StringUtils::EndsWith(strResolution, "i");
+ if(StringUtils::Mid(strResolution, 20,1) == "i")
+ flags |= D3DPRESENTFLAG_INTERLACED;
+
+ if(StringUtils::Mid(strResolution, 21,3) == "sbs")
+ flags |= D3DPRESENTFLAG_MODE3DSBS;
+ else if(StringUtils::Mid(strResolution, 21,3) == "tab")
+ flags |= D3DPRESENTFLAG_MODE3DTB;
std::map<RESOLUTION, RESOLUTION_INFO> resolutionInfos;
for (size_t resolution = RES_DESKTOP; resolution < CDisplaySettings::Get().ResolutionInfoSize(); resolution++)
resolutionInfos.insert(make_pair((RESOLUTION)resolution, CDisplaySettings::Get().GetResolutionInfo(resolution)));
- return FindBestMatchingResolution(resolutionInfos, screen, width, height, refresh, interlaced);
+ return FindBestMatchingResolution(resolutionInfos, screen, width, height, refresh, flags);
}
return RES_DESKTOP;
{
return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen,
info.iScreenWidth, info.iScreenHeight,
- refreshrate > 0.0f ? refreshrate : info.fRefreshRate,
- (info.dwFlags & D3DPRESENTFLAG_INTERLACED) ? "i":"p");
+ refreshrate > 0.0f ? refreshrate : info.fRefreshRate, ModeFlagsToString(info.dwFlags, true).c_str());
}
}
vector<REFRESHRATE> refreshrates = g_Windowing.RefreshRates(resInfo.iScreen, resInfo.iScreenWidth, resInfo.iScreenHeight, resInfo.dwFlags);
bool match = false;
- for (vector<REFRESHRATE>::const_iterator refreshrate = refreshrates.begin(); refreshrate != refreshrates.end(); refreshrate++)
+ for (vector<REFRESHRATE>::const_iterator refreshrate = refreshrates.begin(); refreshrate != refreshrates.end(); ++refreshrate)
{
std::string screenmode = GetStringFromResolution((RESOLUTION)refreshrate->ResInfo_Index, refreshrate->RefreshRate);
if (!match && StringUtils::EqualsNoCase(((CSettingString*)setting)->GetValue(), screenmode))
{
std::map<RESOLUTION, RESOLUTION_INFO> resolutionInfos;
vector<RESOLUTION_WHR> resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate);
- for (vector<RESOLUTION_WHR>::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); resolution++)
+ for (vector<RESOLUTION_WHR>::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution)
{
list.push_back(make_pair(
StringUtils::Format("%dx%d%s", resolution->width, resolution->height,
- (resolution->interlaced == D3DPRESENTFLAG_INTERLACED) ? "i" : "p"),
+ ModeFlagsToString(resolution->flags, false).c_str()),
resolution->ResInfo_Index));
resolutionInfos.insert(make_pair((RESOLUTION)resolution->ResInfo_Index, CDisplaySettings::Get().GetResolutionInfo(resolution->ResInfo_Index)));
current = FindBestMatchingResolution(resolutionInfos, info.iScreen,
info.iScreenWidth, info.iScreenHeight,
- info.fRefreshRate, info.dwFlags & D3DPRESENTFLAG_INTERLACED);
+ info.fRefreshRate, info.dwFlags);
}
}
void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t)
{
-#if defined(_LINUX) && !defined(TARGET_DARWIN)
+ // This ifdef is intended to catch everything except Linux and FreeBSD
+#if defined(TARGET_LINUX) && !defined(TARGET_DARWIN) && !defined(TARGET_ANDROID) && !defined(TARGET_RASPBERRY_PI)
list.push_back(make_pair(g_localizeStrings.Get(13101), VSYNC_DRIVER));
#endif
list.push_back(make_pair(g_localizeStrings.Get(13106), VSYNC_DISABLED));
list.push_back(make_pair(g_localizeStrings.Get(13107), VSYNC_VIDEO));
list.push_back(make_pair(g_localizeStrings.Get(13108), VSYNC_ALWAYS));
}
+
+void CDisplaySettings::SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t)
+{
+ for (int i = RENDER_STEREO_MODE_OFF; i < RENDER_STEREO_MODE_COUNT; i++)
+ {
+ RENDER_STEREO_MODE mode = (RENDER_STEREO_MODE) i;
+ if (g_Windowing.SupportsStereo(mode))
+ list.push_back(make_pair(CStereoscopicsManager::Get().GetLabelForStereoMode(mode), mode));
+ }
+}
+
+void CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int ¤t)
+{
+ SettingOptionsStereoscopicModesFiller(setting, list, current);
+ list.push_back(make_pair(g_localizeStrings.Get(36525), RENDER_STEREO_MODE_AUTO)); // option for autodetect
+}