/*
* Copyright (C) 2005-2013 Team XBMC
* 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
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* .
*
*/
#include "WinSystem.h"
#include "guilib/GraphicContext.h"
#include "settings/DisplaySettings.h"
#include "settings/lib/Setting.h"
#include "settings/Settings.h"
#include "utils/StringUtils.h"
using namespace std;
CWinSystemBase::CWinSystemBase()
{
m_eWindowSystem = WINDOW_SYSTEM_WIN32; // this is the 0 value enum
m_nWidth = 0;
m_nHeight = 0;
m_nTop = 0;
m_nLeft = 0;
m_bWindowCreated = false;
m_bFullScreen = false;
m_nScreen = 0;
m_bBlankOtherDisplay = false;
m_fRefreshRate = 0.0f;
}
CWinSystemBase::~CWinSystemBase()
{
}
bool CWinSystemBase::InitWindowSystem()
{
UpdateResolutions();
CDisplaySettings::Get().ApplyCalibrations();
return true;
}
void CWinSystemBase::UpdateDesktopResolution(RESOLUTION_INFO& newRes, int screen, int width, int height, float refreshRate, uint32_t dwFlags)
{
newRes.Overscan.left = 0;
newRes.Overscan.top = 0;
newRes.Overscan.right = width;
newRes.Overscan.bottom = height;
newRes.iScreen = screen;
newRes.bFullScreen = true;
newRes.iSubtitles = (int)(0.965 * height);
newRes.dwFlags = dwFlags;
newRes.fRefreshRate = refreshRate;
newRes.fPixelRatio = 1.0f;
newRes.iWidth = width;
newRes.iHeight = height;
newRes.iScreenWidth = width;
newRes.iScreenHeight = height;
newRes.strMode = StringUtils::Format("%dx%d", width, height);
if (refreshRate > 1)
newRes.strMode += StringUtils::Format("@ %.2f", refreshRate);
if (dwFlags & D3DPRESENTFLAG_INTERLACED)
newRes.strMode += "i";
if (dwFlags & D3DPRESENTFLAG_MODE3DTB)
newRes.strMode += "tab";
if (dwFlags & D3DPRESENTFLAG_MODE3DSBS)
newRes.strMode += "sbs";
if (screen > 0)
newRes.strMode = StringUtils::Format("%s #%d", newRes.strMode.c_str(), screen + 1);
if (refreshRate > 1)
newRes.strMode += " - Full Screen";
}
void CWinSystemBase::UpdateResolutions()
{
// add the window res - defaults are fine.
RESOLUTION_INFO& window = CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW);
window.bFullScreen = false;
if (window.iWidth == 0)
window.iWidth = 720;
if (window.iHeight == 0)
window.iHeight = 480;
window.iScreenWidth = window.iWidth;
window.iScreenHeight = window.iHeight;
if (window.iSubtitles == 0)
window.iSubtitles = (int)(0.965 * window.iHeight);
window.fPixelRatio = 1.0f;
window.strMode = "Windowed";
}
void CWinSystemBase::SetWindowResolution(int width, int height)
{
RESOLUTION_INFO& window = CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW);
window.iWidth = width;
window.iHeight = height;
window.iScreenWidth = width;
window.iScreenHeight = height;
window.iSubtitles = (int)(0.965 * window.iHeight);
g_graphicsContext.ResetOverscan(window);
}
int CWinSystemBase::DesktopResolution(int screen)
{
for (int idx = 0; idx < GetNumScreens(); idx++)
if (CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen == screen)
return RES_DESKTOP + idx;
// Uh? something's wrong, fallback to default res of main screen
return RES_DESKTOP;
}
static void AddResolution(vector &resolutions, unsigned int addindex, float bestRefreshrate)
{
RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(addindex);
int width = resInfo.iScreenWidth;
int height = resInfo.iScreenHeight;
int flags = resInfo.dwFlags & D3DPRESENTFLAG_MODEMASK;
float refreshrate = resInfo.fRefreshRate;
// don't touch RES_DESKTOP
for (unsigned int idx = 1; idx < resolutions.size(); idx++)
if ( resolutions[idx].width == width
&& resolutions[idx].height == height
&&(resolutions[idx].flags & D3DPRESENTFLAG_MODEMASK) == flags)
{
// check if the refresh rate of this resolution is better suited than
// the refresh rate of the resolution with the same width/height/interlaced
// property and if so replace it
if (bestRefreshrate > 0.0 && refreshrate == bestRefreshrate)
resolutions[idx].ResInfo_Index = addindex;
// no need to add the resolution again
return;
}
RESOLUTION_WHR res = {width, height, flags, (int)addindex};
resolutions.push_back(res);
}
static bool resSortPredicate(RESOLUTION_WHR i, RESOLUTION_WHR j)
{
// note: this comparison must obey "strict weak ordering"
// a "!=" on the flags comparison resulted in memory corruption
return ( i.width < j.width
|| (i.width == j.width && i.height < j.height)
|| (i.width == j.width && i.height == j.height && i.flags < j.flags) );
}
vector CWinSystemBase::ScreenResolutions(int screen, float refreshrate)
{
vector resolutions;
for (unsigned int idx = RES_DESKTOP; idx < CDisplaySettings::Get().ResolutionInfoSize(); idx++)
{
RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(idx);
if (info.iScreen == screen)
AddResolution(resolutions, idx, refreshrate);
}
// Can't assume a sort order
// don't touch RES_DESKTOP which is index 0
sort(resolutions.begin()+1, resolutions.end(), resSortPredicate);
return resolutions;
}
static void AddRefreshRate(vector &refreshrates, unsigned int addindex)
{
float RefreshRate = CDisplaySettings::Get().GetResolutionInfo(addindex).fRefreshRate;
for (unsigned int idx = 0; idx < refreshrates.size(); idx++)
if ( refreshrates[idx].RefreshRate == RefreshRate)
return; // already taken care of.
REFRESHRATE rr = {RefreshRate, (int)addindex};
refreshrates.push_back(rr);
}
static bool rrSortPredicate(REFRESHRATE i, REFRESHRATE j)
{
return (i.RefreshRate < j.RefreshRate);
}
vector CWinSystemBase::RefreshRates(int screen, int width, int height, uint32_t dwFlags)
{
vector refreshrates;
for (unsigned int idx = RES_DESKTOP; idx < CDisplaySettings::Get().ResolutionInfoSize(); idx++)
if ( CDisplaySettings::Get().GetResolutionInfo(idx).iScreen == screen
&& CDisplaySettings::Get().GetResolutionInfo(idx).iScreenWidth == width
&& CDisplaySettings::Get().GetResolutionInfo(idx).iScreenHeight == height
&& (CDisplaySettings::Get().GetResolutionInfo(idx).dwFlags & D3DPRESENTFLAG_MODEMASK) == (dwFlags & D3DPRESENTFLAG_MODEMASK))
AddRefreshRate(refreshrates, idx);
// Can't assume a sort order
sort(refreshrates.begin(), refreshrates.end(), rrSortPredicate);
return refreshrates;
}
REFRESHRATE CWinSystemBase::DefaultRefreshRate(int screen, vector rates)
{
REFRESHRATE bestmatch = rates[0];
float bestfitness = -1.0f;
float targetfps = CDisplaySettings::Get().GetResolutionInfo(DesktopResolution(screen)).fRefreshRate;
for (unsigned i = 0; i < rates.size(); i++)
{
float fitness = fabs(targetfps - rates[i].RefreshRate);
if (bestfitness <0 || fitness < bestfitness)
{
bestfitness = fitness;
bestmatch = rates[i];
if (bestfitness == 0.0f) // perfect match
break;
}
}
return bestmatch;
}
bool CWinSystemBase::UseLimitedColor()
{
#if defined(HAS_GL) || defined(HAS_DX)
static CSettingBool* setting = (CSettingBool*)CSettings::Get().GetSetting("videoscreen.limitedrange");
return setting->GetValue();
#else
return false;
#endif
}
std::string CWinSystemBase::GetClipboardText(void)
{
return "";
}