DVDCodecs: Amlogic: Handle conditions in which amcodec should be opened during Open()
[vuplus_xbmc] / xbmc / settings / DisplaySettings.cpp
1 /*
2  *      Copyright (C) 2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <float.h>
22 #include <stdlib.h>
23
24 #include "DisplaySettings.h"
25 #include "dialogs/GUIDialogYesNo.h"
26 #include "guilib/GraphicContext.h"
27 #include "guilib/gui3d.h"
28 #include "guilib/LocalizeStrings.h"
29 #include "guilib/StereoscopicsManager.h"
30 #include "settings/AdvancedSettings.h"
31 #include "settings/lib/Setting.h"
32 #include "settings/Settings.h"
33 #include "threads/SingleLock.h"
34 #include "utils/log.h"
35 #include "utils/StringUtils.h"
36 #include "utils/XMLUtils.h"
37 #include "windowing/WindowingFactory.h"
38
39 // 0.1 second increments
40 #define MAX_REFRESH_CHANGE_DELAY 200
41
42 using namespace std;
43
44 static RESOLUTION_INFO EmptyResolution;
45 static RESOLUTION_INFO EmptyModifiableResolution;
46
47 float square_error(float x, float y)
48 {
49   float yonx = (x > 0) ? y / x : 0;
50   float xony = (y > 0) ? x / y : 0;
51   return std::max(yonx, xony);
52 }
53
54 static CStdString ModeFlagsToString(unsigned int flags, bool identifier)
55 {
56   CStdString res;
57   if(flags & D3DPRESENTFLAG_INTERLACED)
58     res += "i";
59   else
60     res += "p";
61
62   if(!identifier)
63     res += " ";
64
65   if(flags & D3DPRESENTFLAG_MODE3DSBS)
66     res += "sbs";
67   else if(flags & D3DPRESENTFLAG_MODE3DTB)
68     res += "tab";
69   else if(identifier)
70     res += "std";
71   return res;
72 }
73
74 CDisplaySettings::CDisplaySettings()
75 {
76   m_resolutions.insert(m_resolutions.begin(), RES_CUSTOM, RESOLUTION_INFO());
77
78   m_zoomAmount = 1.0f;
79   m_pixelRatio = 1.0f;
80   m_verticalShift = 0.0f;
81   m_nonLinearStretched = false;
82   m_resolutionChangeAborted = false;
83 }
84
85 CDisplaySettings::~CDisplaySettings()
86 { }
87
88 CDisplaySettings& CDisplaySettings::Get()
89 {
90   static CDisplaySettings sDisplaySettings;
91   return sDisplaySettings;
92 }
93
94 bool CDisplaySettings::Load(const TiXmlNode *settings)
95 {
96   CSingleLock lock(m_critical);
97   m_calibrations.clear();
98
99   if (settings == NULL)
100     return false;
101
102   const TiXmlElement *pElement = settings->FirstChildElement("resolutions");
103   if (!pElement)
104   {
105     CLog::Log(LOGERROR, "CDisplaySettings: settings file doesn't contain <resolutions>");
106     return false;
107   }
108
109   const TiXmlElement *pResolution = pElement->FirstChildElement("resolution");
110   while (pResolution)
111   {
112     // get the data for this calibration
113     RESOLUTION_INFO cal;
114
115     XMLUtils::GetString(pResolution, "description", cal.strMode);
116     XMLUtils::GetInt(pResolution, "subtitles", cal.iSubtitles);
117     XMLUtils::GetFloat(pResolution, "pixelratio", cal.fPixelRatio);
118 #ifdef HAS_XRANDR
119     XMLUtils::GetFloat(pResolution, "refreshrate", cal.fRefreshRate);
120     XMLUtils::GetString(pResolution, "output", cal.strOutput);
121     XMLUtils::GetString(pResolution, "xrandrid", cal.strId);
122 #endif
123
124     const TiXmlElement *pOverscan = pResolution->FirstChildElement("overscan");
125     if (pOverscan)
126     {
127       XMLUtils::GetInt(pOverscan, "left", cal.Overscan.left);
128       XMLUtils::GetInt(pOverscan, "top", cal.Overscan.top);
129       XMLUtils::GetInt(pOverscan, "right", cal.Overscan.right);
130       XMLUtils::GetInt(pOverscan, "bottom", cal.Overscan.bottom);
131     }
132
133     // mark calibration as not updated
134     // we must not delete those, resolution just might not be available
135     cal.iWidth = cal.iHeight = 0;
136
137     // store calibration, avoid adding duplicates
138     bool found = false;
139     for (ResolutionInfos::const_iterator  it = m_calibrations.begin(); it != m_calibrations.end(); ++it)
140     {
141       if (it->strMode.Equals(cal.strMode))
142       {
143         found = true;
144         break;
145       }
146     }
147     if (!found)
148       m_calibrations.push_back(cal);
149
150     // iterate around
151     pResolution = pResolution->NextSiblingElement("resolution");
152   }
153
154   ApplyCalibrations();
155   return true;
156 }
157
158 bool CDisplaySettings::Save(TiXmlNode *settings) const
159 {
160   if (settings == NULL)
161     return false;
162
163   CSingleLock lock(m_critical);
164   TiXmlElement xmlRootElement("resolutions");
165   TiXmlNode *pRoot = settings->InsertEndChild(xmlRootElement);
166   if (pRoot == NULL)
167     return false;
168
169   // save calibrations
170   for (ResolutionInfos::const_iterator it = m_calibrations.begin(); it != m_calibrations.end(); ++it)
171   {
172     // Write the resolution tag
173     TiXmlElement resElement("resolution");
174     TiXmlNode *pNode = pRoot->InsertEndChild(resElement);
175     if (pNode == NULL)
176       return false;
177
178     // Now write each of the pieces of information we need...
179     XMLUtils::SetString(pNode, "description", it->strMode);
180     XMLUtils::SetInt(pNode, "subtitles", it->iSubtitles);
181     XMLUtils::SetFloat(pNode, "pixelratio", it->fPixelRatio);
182 #ifdef HAS_XRANDR
183     XMLUtils::SetFloat(pNode, "refreshrate", it->fRefreshRate);
184     XMLUtils::SetString(pNode, "output", it->strOutput);
185     XMLUtils::SetString(pNode, "xrandrid", it->strId);
186 #endif
187
188     // create the overscan child
189     TiXmlElement overscanElement("overscan");
190     TiXmlNode *pOverscanNode = pNode->InsertEndChild(overscanElement);
191     if (pOverscanNode == NULL)
192       return false;
193
194     XMLUtils::SetInt(pOverscanNode, "left", it->Overscan.left);
195     XMLUtils::SetInt(pOverscanNode, "top", it->Overscan.top);
196     XMLUtils::SetInt(pOverscanNode, "right", it->Overscan.right);
197     XMLUtils::SetInt(pOverscanNode, "bottom", it->Overscan.bottom);
198   }
199
200   return true;
201 }
202
203 void CDisplaySettings::Clear()
204 {
205   CSingleLock lock(m_critical);
206   m_calibrations.clear();
207   m_resolutions.clear();
208
209   m_zoomAmount = 1.0f;
210   m_pixelRatio = 1.0f;
211   m_verticalShift = 0.0f;
212   m_nonLinearStretched = false;
213 }
214
215 bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
216 {
217   if (setting == NULL)
218     return false;
219
220   const std::string &settingId = setting->GetId();
221   if (settingId == "videoscreen.resolution" ||
222       settingId == "videoscreen.screen")
223   {
224     RESOLUTION newRes = RES_DESKTOP;
225     if (settingId == "videoscreen.resolution")
226       newRes = (RESOLUTION)((CSettingInt*)setting)->GetValue();
227     else if (settingId == "videoscreen.screen")
228       newRes = GetResolutionForScreen();
229
230     string screenmode = GetStringFromResolution(newRes);
231     CSettings::Get().SetString("videoscreen.screenmode", screenmode);
232   }
233   if (settingId == "videoscreen.screenmode")
234   {
235     RESOLUTION oldRes = GetCurrentResolution();
236     RESOLUTION newRes = GetResolutionFromString(((CSettingString*)setting)->GetValue());
237
238     SetCurrentResolution(newRes, false);
239     g_graphicsContext.SetVideoResolution(newRes);
240
241     // check if the old or the new resolution was/is windowed
242     // in which case we don't show any prompt to the user
243     if (oldRes != RES_WINDOW && newRes != RES_WINDOW && oldRes != newRes)
244     {
245       if (!m_resolutionChangeAborted)
246       {
247         bool cancelled = false;
248         if (!CGUIDialogYesNo::ShowAndGetInput(13110, 13111, 20022, 20022, -1, -1, cancelled, 10000))
249         {
250           m_resolutionChangeAborted = true;
251           return false;
252         }
253       }
254       else
255         m_resolutionChangeAborted = false;
256     }
257   }
258
259   return true;
260 }
261
262 bool CDisplaySettings::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
263 {
264   if (setting == NULL)
265     return false;
266
267   const std::string &settingId = setting->GetId();
268   if (settingId == "videoscreen.screenmode")
269   {
270     CSettingString *screenmodeSetting = (CSettingString*)setting;
271     std::string screenmode = screenmodeSetting->GetValue();
272     // in Eden there was no character ("i" or "p") indicating interlaced/progressive
273     // at the end so we just add a "p" and assume progressive
274     // no 3d mode existed before, so just assume std modes
275     if (screenmode.size() == 20)
276       return screenmodeSetting->SetValue(screenmode + "pstd");
277     if (screenmode.size() == 21)
278       return screenmodeSetting->SetValue(screenmode + "std");
279   }
280   else if (settingId == "videoscreen.vsync")
281   {
282     // This ifdef is intended to catch everything except Linux and FreeBSD
283 #if !defined(TARGET_LINUX) || defined(TARGET_DARWIN) || defined(TARGET_ANDROID) || defined(TARGET_RASPBERRY_PI)
284     // in the Gotham alphas through beta3 the default value for darwin and android was set incorrectly.
285     CSettingInt *vsyncSetting = (CSettingInt*)setting;
286     if (vsyncSetting->GetValue() == VSYNC_DRIVER)
287       return vsyncSetting->SetValue(VSYNC_ALWAYS);
288 #endif
289   }
290
291   return false;
292 }
293
294 void CDisplaySettings::SetCurrentResolution(RESOLUTION resolution, bool save /* = false */)
295 {
296   if (save)
297   {
298     string mode = GetStringFromResolution(resolution);
299     CSettings::Get().SetString("videoscreen.screenmode", mode.c_str());
300   }
301
302   m_currentResolution = resolution;
303
304   SetChanged();
305 }
306
307 RESOLUTION CDisplaySettings::GetDisplayResolution() const
308 {
309   return GetResolutionFromString(CSettings::Get().GetString("videoscreen.screenmode"));
310 }
311
312 const RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(size_t index) const
313 {
314   CSingleLock lock(m_critical);
315   if (index >= m_resolutions.size())
316     return EmptyResolution;
317
318   return m_resolutions[index];
319 }
320
321 const RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(RESOLUTION resolution) const
322 {
323   if (resolution <= RES_INVALID)
324     return EmptyResolution;
325
326   return GetResolutionInfo((size_t)resolution);
327 }
328
329 RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(size_t index)
330 {
331   CSingleLock lock(m_critical);
332   if (index >= m_resolutions.size())
333   {
334     EmptyModifiableResolution = RESOLUTION_INFO();
335     return EmptyModifiableResolution;
336   }
337
338   return m_resolutions[index];
339 }
340
341 RESOLUTION_INFO& CDisplaySettings::GetResolutionInfo(RESOLUTION resolution)
342 {
343   if (resolution <= RES_INVALID)
344   {
345     EmptyModifiableResolution = RESOLUTION_INFO();
346     return EmptyModifiableResolution;
347   }
348
349   return GetResolutionInfo((size_t)resolution);
350 }
351
352 void CDisplaySettings::AddResolutionInfo(const RESOLUTION_INFO &resolution)
353 {
354   CSingleLock lock(m_critical);
355   RESOLUTION_INFO res(resolution);
356
357   if((res.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
358   {
359     /* add corrections for some special case modes frame packing modes */
360
361     if(res.iScreenWidth  == 1920
362     && res.iScreenHeight == 2205)
363     {
364       res.iBlanking = 45;
365       res.dwFlags  |= D3DPRESENTFLAG_MODE3DTB;
366     }
367
368     if(res.iScreenWidth  == 1280
369     && res.iScreenHeight == 1470)
370     {
371       res.iBlanking = 30;
372       res.dwFlags  |= D3DPRESENTFLAG_MODE3DTB;
373     }
374   }
375   m_resolutions.push_back(res);
376 }
377
378 void CDisplaySettings::ApplyCalibrations()
379 {
380   CSingleLock lock(m_critical);
381   // apply all calibrations to the resolutions
382   for (ResolutionInfos::const_iterator itCal = m_calibrations.begin(); itCal != m_calibrations.end(); ++itCal)
383   {
384     // find resolutions
385     for (size_t res = 0; res < m_resolutions.size(); ++res)
386     {
387       if (res == RES_WINDOW)
388         continue;
389       if (itCal->strMode.Equals(m_resolutions[res].strMode))
390       {
391         // overscan
392         m_resolutions[res].Overscan.left = itCal->Overscan.left;
393         if (m_resolutions[res].Overscan.left < -m_resolutions[res].iWidth/4)
394           m_resolutions[res].Overscan.left = -m_resolutions[res].iWidth/4;
395         if (m_resolutions[res].Overscan.left > m_resolutions[res].iWidth/4)
396           m_resolutions[res].Overscan.left = m_resolutions[res].iWidth/4;
397
398         m_resolutions[res].Overscan.top = itCal->Overscan.top;
399         if (m_resolutions[res].Overscan.top < -m_resolutions[res].iHeight/4)
400           m_resolutions[res].Overscan.top = -m_resolutions[res].iHeight/4;
401         if (m_resolutions[res].Overscan.top > m_resolutions[res].iHeight/4)
402           m_resolutions[res].Overscan.top = m_resolutions[res].iHeight/4;
403
404         m_resolutions[res].Overscan.right = itCal->Overscan.right;
405         if (m_resolutions[res].Overscan.right < m_resolutions[res].iWidth / 2)
406           m_resolutions[res].Overscan.right = m_resolutions[res].iWidth / 2;
407         if (m_resolutions[res].Overscan.right > m_resolutions[res].iWidth * 3/2)
408           m_resolutions[res].Overscan.right = m_resolutions[res].iWidth *3/2;
409
410         m_resolutions[res].Overscan.bottom = itCal->Overscan.bottom;
411         if (m_resolutions[res].Overscan.bottom < m_resolutions[res].iHeight / 2)
412           m_resolutions[res].Overscan.bottom = m_resolutions[res].iHeight / 2;
413         if (m_resolutions[res].Overscan.bottom > m_resolutions[res].iHeight * 3/2)
414           m_resolutions[res].Overscan.bottom = m_resolutions[res].iHeight * 3/2;
415
416         m_resolutions[res].iSubtitles = itCal->iSubtitles;
417         if (m_resolutions[res].iSubtitles < m_resolutions[res].iHeight / 2)
418           m_resolutions[res].iSubtitles = m_resolutions[res].iHeight / 2;
419         if (m_resolutions[res].iSubtitles > m_resolutions[res].iHeight* 5/4)
420           m_resolutions[res].iSubtitles = m_resolutions[res].iHeight* 5/4;
421
422         m_resolutions[res].fPixelRatio = itCal->fPixelRatio;
423         if (m_resolutions[res].fPixelRatio < 0.5f)
424           m_resolutions[res].fPixelRatio = 0.5f;
425         if (m_resolutions[res].fPixelRatio > 2.0f)
426           m_resolutions[res].fPixelRatio = 2.0f;
427         break;
428       }
429     }
430   }
431 }
432
433 void CDisplaySettings::UpdateCalibrations()
434 {
435   CSingleLock lock(m_critical);
436   for (size_t res = RES_DESKTOP; res < m_resolutions.size(); ++res)
437   {
438     // find calibration
439     bool found = false;
440     for (ResolutionInfos::iterator itCal = m_calibrations.begin(); itCal != m_calibrations.end(); ++itCal)
441     {
442       if (itCal->strMode.Equals(m_resolutions[res].strMode))
443       {
444         // TODO: erase calibrations with default values
445         *itCal = m_resolutions[res];
446         found = true;
447         break;
448       }
449     }
450
451     if (!found)
452       m_calibrations.push_back(m_resolutions[res]);
453   }
454 }
455
456 DisplayMode CDisplaySettings::GetCurrentDisplayMode() const
457 {
458   if (GetCurrentResolution() == RES_WINDOW)
459     return DM_WINDOWED;
460
461   return GetCurrentResolutionInfo().iScreen;
462 }
463
464 RESOLUTION CDisplaySettings::FindBestMatchingResolution(const std::map<RESOLUTION, RESOLUTION_INFO> &resolutionInfos, int screen, int width, int height, float refreshrate, unsigned flags)
465 {
466   // find the closest match to these in our res vector.  If we have the screen, we score the res
467   RESOLUTION bestRes = RES_DESKTOP;
468   float bestScore = FLT_MAX;
469   flags &= D3DPRESENTFLAG_MODEMASK;
470
471   for (std::map<RESOLUTION, RESOLUTION_INFO>::const_iterator it = resolutionInfos.begin(); it != resolutionInfos.end(); ++it)
472   {
473     const RESOLUTION_INFO &info = it->second;
474
475     if ( info.iScreen               != screen
476     ||  (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != flags)
477       continue;
478
479     float score = 10 * (square_error((float)info.iScreenWidth, (float)width) +
480                   square_error((float)info.iScreenHeight, (float)height) +
481                   square_error(info.fRefreshRate, refreshrate));
482     if (score < bestScore)
483     {
484       bestScore = score;
485       bestRes = it->first;
486     }
487   }
488
489   return bestRes;
490 }
491
492 RESOLUTION CDisplaySettings::GetResolutionFromString(const std::string &strResolution)
493 {
494   if (strResolution == "DESKTOP")
495     return RES_DESKTOP;
496   else if (strResolution == "WINDOW")
497     return RES_WINDOW;
498   else if (strResolution.size() >= 21)
499   {
500     // format: SWWWWWHHHHHRRR.RRRRRP333, where S = screen, W = width, H = height, R = refresh, P = interlace, 3 = stereo mode
501     int screen = strtol(StringUtils::Mid(strResolution, 0,1).c_str(), NULL, 10);
502     int width = strtol(StringUtils::Mid(strResolution, 1,5).c_str(), NULL, 10);
503     int height = strtol(StringUtils::Mid(strResolution, 6,5).c_str(), NULL, 10);
504     float refresh = (float)strtod(StringUtils::Mid(strResolution, 11,9).c_str(), NULL);
505     unsigned flags = 0;
506
507     // look for 'i' and treat everything else as progressive,
508     if(StringUtils::Mid(strResolution, 20,1) == "i")
509       flags |= D3DPRESENTFLAG_INTERLACED;
510
511     if(StringUtils::Mid(strResolution, 21,3) == "sbs")
512       flags |= D3DPRESENTFLAG_MODE3DSBS;
513     else if(StringUtils::Mid(strResolution, 21,3) == "tab")
514       flags |= D3DPRESENTFLAG_MODE3DTB;
515
516     std::map<RESOLUTION, RESOLUTION_INFO> resolutionInfos;
517     for (size_t resolution = RES_DESKTOP; resolution < CDisplaySettings::Get().ResolutionInfoSize(); resolution++)
518       resolutionInfos.insert(make_pair((RESOLUTION)resolution, CDisplaySettings::Get().GetResolutionInfo(resolution)));
519
520     return FindBestMatchingResolution(resolutionInfos, screen, width, height, refresh, flags);
521   }
522
523   return RES_DESKTOP;
524 }
525
526 std::string CDisplaySettings::GetStringFromResolution(RESOLUTION resolution, float refreshrate /* = 0.0f */)
527 {
528   if (resolution == RES_WINDOW)
529     return "WINDOW";
530
531   if (resolution >= RES_DESKTOP && resolution < (RESOLUTION)CDisplaySettings::Get().ResolutionInfoSize())
532   {
533     const RESOLUTION_INFO &info = CDisplaySettings::Get().GetResolutionInfo(resolution);
534     // also handle RES_DESKTOP resolutions with non-default refresh rates
535     if (resolution != RES_DESKTOP || (refreshrate > 0.0f && refreshrate != info.fRefreshRate))
536     {
537       return StringUtils::Format("%1i%05i%05i%09.5f%s", info.iScreen,
538                                  info.iScreenWidth, info.iScreenHeight,
539                                  refreshrate > 0.0f ? refreshrate : info.fRefreshRate, ModeFlagsToString(info.dwFlags, true).c_str());
540     }
541   }
542
543   return "DESKTOP";
544 }
545
546 RESOLUTION CDisplaySettings::GetResolutionForScreen()
547 {
548   DisplayMode mode = CSettings::Get().GetInt("videoscreen.screen");
549   if (mode == DM_WINDOWED)
550     return RES_WINDOW;
551
552   for (int idx=0; idx < g_Windowing.GetNumScreens(); idx++)
553   {
554     if (CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen == mode)
555       return (RESOLUTION)(RES_DESKTOP + idx);
556   }
557
558   return RES_DESKTOP;
559 }
560
561 void CDisplaySettings::SettingOptionsRefreshChangeDelaysFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
562 {
563   list.push_back(make_pair(g_localizeStrings.Get(13551), 0));
564           
565   for (int i = 1; i <= MAX_REFRESH_CHANGE_DELAY; i++)
566     list.push_back(make_pair(StringUtils::Format(g_localizeStrings.Get(13553).c_str(), (double)i / 10.0), i));
567 }
568
569 void CDisplaySettings::SettingOptionsRefreshRatesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current)
570 {
571   // get the proper resolution
572   RESOLUTION res = CDisplaySettings::Get().GetDisplayResolution();
573   if (res < RES_WINDOW)
574     return;
575
576   // only add "Windowed" if in windowed mode
577   if (res == RES_WINDOW)
578   {
579     current = "WINDOW";
580     list.push_back(make_pair(g_localizeStrings.Get(242), current));
581     return;
582   }
583
584   RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(res);
585   // The only meaningful parts of res here are iScreen, iScreenWidth, iScreenHeight
586   vector<REFRESHRATE> refreshrates = g_Windowing.RefreshRates(resInfo.iScreen, resInfo.iScreenWidth, resInfo.iScreenHeight, resInfo.dwFlags);
587
588   bool match = false;
589   for (vector<REFRESHRATE>::const_iterator refreshrate = refreshrates.begin(); refreshrate != refreshrates.end(); ++refreshrate)
590   {
591     std::string screenmode = GetStringFromResolution((RESOLUTION)refreshrate->ResInfo_Index, refreshrate->RefreshRate);
592     if (!match && StringUtils::EqualsNoCase(((CSettingString*)setting)->GetValue(), screenmode))
593       match = true;
594     list.push_back(make_pair(StringUtils::Format("%.02f", refreshrate->RefreshRate), screenmode));
595   }
596
597   if (!match)
598     current = GetStringFromResolution(res, g_Windowing.DefaultRefreshRate(resInfo.iScreen, refreshrates).RefreshRate);
599 }
600
601 void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
602 {
603   RESOLUTION res = CDisplaySettings::Get().GetDisplayResolution();
604   RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res);
605   if (res == RES_WINDOW)
606   {
607     current = res;
608     list.push_back(make_pair(g_localizeStrings.Get(242), res));
609   }
610   else
611   {
612     std::map<RESOLUTION, RESOLUTION_INFO> resolutionInfos;
613     vector<RESOLUTION_WHR> resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate);
614     for (vector<RESOLUTION_WHR>::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution)
615     {
616       list.push_back(make_pair(
617         StringUtils::Format("%dx%d%s", resolution->width, resolution->height,
618                             ModeFlagsToString(resolution->flags, false).c_str()),
619                             resolution->ResInfo_Index));
620
621       resolutionInfos.insert(make_pair((RESOLUTION)resolution->ResInfo_Index, CDisplaySettings::Get().GetResolutionInfo(resolution->ResInfo_Index)));
622     }
623
624     current = FindBestMatchingResolution(resolutionInfos, info.iScreen,
625                                          info.iScreenWidth, info.iScreenHeight,
626                                          info.fRefreshRate, info.dwFlags);
627   }
628 }
629
630 void CDisplaySettings::SettingOptionsScreensFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
631 {
632   if (g_advancedSettings.m_canWindowed)
633     list.push_back(make_pair(g_localizeStrings.Get(242), DM_WINDOWED));
634
635   for (int idx = 0; idx < g_Windowing.GetNumScreens(); idx++)
636   {
637     int screen = CDisplaySettings::Get().GetResolutionInfo(RES_DESKTOP + idx).iScreen;
638     list.push_back(make_pair(StringUtils::Format(g_localizeStrings.Get(241), screen + 1), screen));
639   }
640
641   RESOLUTION res = CDisplaySettings::Get().GetDisplayResolution();
642   if (res == RES_WINDOW)
643     current = DM_WINDOWED;
644   else
645   {
646     RESOLUTION_INFO resInfo = CDisplaySettings::Get().GetResolutionInfo(res);
647     current = resInfo.iScreen;
648   }
649 }
650
651 void CDisplaySettings::SettingOptionsVerticalSyncsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
652 {
653   // This ifdef is intended to catch everything except Linux and FreeBSD
654 #if defined(TARGET_LINUX) && !defined(TARGET_DARWIN) && !defined(TARGET_ANDROID) && !defined(TARGET_RASPBERRY_PI)
655   list.push_back(make_pair(g_localizeStrings.Get(13101), VSYNC_DRIVER));
656 #endif
657   list.push_back(make_pair(g_localizeStrings.Get(13106), VSYNC_DISABLED));
658   list.push_back(make_pair(g_localizeStrings.Get(13107), VSYNC_VIDEO));
659   list.push_back(make_pair(g_localizeStrings.Get(13108), VSYNC_ALWAYS));
660 }
661
662 void CDisplaySettings::SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
663 {
664   for (int i = RENDER_STEREO_MODE_OFF; i < RENDER_STEREO_MODE_COUNT; i++)
665   {
666     RENDER_STEREO_MODE mode = (RENDER_STEREO_MODE) i;
667     if (g_Windowing.SupportsStereo(mode))
668       list.push_back(make_pair(CStereoscopicsManager::Get().GetLabelForStereoMode(mode), mode));
669   }
670 }
671
672 void CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current)
673 {
674   SettingOptionsStereoscopicModesFiller(setting, list, current);
675   list.push_back(make_pair(g_localizeStrings.Get(36525), RENDER_STEREO_MODE_AUTO)); // option for autodetect
676 }