DisplayManager.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. //
  2. // DisplayManager.cpp
  3. // konvergo
  4. //
  5. // Created by Lionel CHAZALLON on 28/09/2014.
  6. //
  7. //
  8. #include "QsLog.h"
  9. #include "DisplayManager.h"
  10. #include "math.h"
  11. #include "settings/SettingsComponent.h"
  12. ///////////////////////////////////////////////////////////////////////////////////////////////////
  13. DisplayManager::DisplayManager(QObject* parent) : QObject(parent) {}
  14. ///////////////////////////////////////////////////////////////////////////////////////////////////
  15. bool DisplayManager::initialize()
  16. {
  17. QLOG_INFO() << QString("DisplayManager found %1 Display(s).").arg(m_displays.size());
  18. // list video modes
  19. for(int displayid : m_displays.keys())
  20. {
  21. DMDisplayPtr display = m_displays[displayid];
  22. QLOG_INFO() << QString("Available modes for Display #%1 (%2)").arg(displayid).arg(display->m_name);
  23. for (int modeid = 0; modeid < display->m_videoModes.size(); modeid++)
  24. {
  25. DMVideoModePtr mode = display->m_videoModes[modeid];
  26. QLOG_INFO() << QString("Mode %1: %2").arg(modeid, 2).arg(mode->getPrettyName());
  27. }
  28. }
  29. // Log current display mode
  30. int mainDisplay = getMainDisplay();
  31. if (mainDisplay >= 0)
  32. {
  33. int currentMode = getCurrentDisplayMode(mainDisplay);
  34. if (currentMode >= 0)
  35. QLOG_INFO() << QString("DisplayManager : Current Display Mode on Display #%1 is %2")
  36. .arg(mainDisplay)
  37. .arg(m_displays[mainDisplay]->m_videoModes[currentMode]->getPrettyName());
  38. else
  39. QLOG_ERROR() << "DisplayManager : unable to retrieve current video mode";
  40. }
  41. else
  42. QLOG_ERROR() << "DisplayManager : unable to retrieve main display";
  43. return true;
  44. }
  45. ///////////////////////////////////////////////////////////////////////////////////////////////////
  46. DMVideoModePtr DisplayManager::getCurrentVideoMode(int display)
  47. {
  48. int currentMode = getCurrentDisplayMode(display);
  49. DMVideoModePtr currentVideoMode;
  50. if (currentMode >= 0)
  51. currentVideoMode = m_displays[display]->m_videoModes[currentMode];
  52. return currentVideoMode;
  53. }
  54. ///////////////////////////////////////////////////////////////////////////////////////////////////
  55. bool DisplayManager::isValidDisplay(int display) { return m_displays.contains(display); }
  56. ///////////////////////////////////////////////////////////////////////////////////////////////////
  57. bool DisplayManager::isValidDisplayMode(int display, int mode)
  58. {
  59. if (isValidDisplay(display))
  60. if (mode >= 0 && mode < m_displays[display]->m_videoModes.size())
  61. return true;
  62. return false;
  63. }
  64. ///////////////////////////////////////////////////////////////////////////////////////////////////
  65. // refresh: video FPS
  66. // multiple: display FPS
  67. bool DisplayManager::isRateMultipleOf(float refresh, float multiple, bool exact)
  68. {
  69. long roundedRefresh = lrint(refresh);
  70. long roundedMultiple = lrint(multiple);
  71. if (roundedRefresh == 0)
  72. return false;
  73. long factor = roundedMultiple / roundedRefresh;
  74. float newRate = factor * refresh;
  75. if (newRate < 1)
  76. return false;
  77. float tolerance = exact ? 0.01 * factor : 1;
  78. return fabs(newRate - multiple) < tolerance;
  79. }
  80. ///////////////////////////////////////////////////////////////////////////////////////////////////
  81. int DisplayManager::findBestMatch(int display, DMMatchMediaInfo& matchInfo)
  82. {
  83. bool avoid_25_30 = SettingsComponent::Get().value(SETTINGS_SECTION_VIDEO, "refreshrate.avoid_25hz_30hz").toBool();
  84. // Grab current videomode information
  85. DMVideoModePtr currentVideoMode = getCurrentVideoMode(display);
  86. if (!currentVideoMode)
  87. return -1;
  88. // now we try to find the exact match in current resolution
  89. // then fill a list
  90. DMVideoModeWeightMap weights;
  91. DMVideoModeMap::const_iterator modeit = m_displays[display]->m_videoModes.constBegin();
  92. while (modeit != m_displays[display]->m_videoModes.constEnd())
  93. {
  94. DMVideoModePtr candidate = modeit.value();
  95. // avoid switching to 30 fps (prefer a multiple - 60Hz is ideal)
  96. // the intention is also to match 30/1.001
  97. if ((fabs(candidate->m_refreshRate - 30.0) < 0.5) ||
  98. (fabs(candidate->m_refreshRate - 25.0) < 0.5))
  99. {
  100. if (avoid_25_30)
  101. {
  102. QLOG_INFO() << "DisplayManager RefreshMatch : skipping rate " << candidate->m_refreshRate << "as requested";
  103. modeit++;
  104. continue;
  105. }
  106. }
  107. weights[candidate->m_id] = DMVideoModeWeightPtr(new DMVideoModeWeight);
  108. weights[candidate->m_id]->m_mode = candidate;
  109. weights[candidate->m_id]->m_weight = 0;
  110. // Weight Resolution match
  111. if ((candidate->m_width == currentVideoMode->m_width) &&
  112. (candidate->m_height == currentVideoMode->m_height) &&
  113. (candidate->m_bitsPerPixel == currentVideoMode->m_bitsPerPixel))
  114. {
  115. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_RES;
  116. }
  117. // weight refresh rate
  118. // exact Match
  119. if (fabs(candidate->m_refreshRate - matchInfo.m_refreshRate) <= 0.01)
  120. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_REFRESH_RATE_EXACT;
  121. // exact multiple refresh rate
  122. if (isRateMultipleOf(matchInfo.m_refreshRate, candidate->m_refreshRate, true))
  123. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_REFRESH_RATE_MULTIPLE;
  124. // close refresh match (less than 1 hz diff to match all 23.xxx modes to 24p)
  125. if (fabs(candidate->m_refreshRate - matchInfo.m_refreshRate) <= 0.5)
  126. {
  127. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_REFRESH_RATE_CLOSE;
  128. }
  129. // approx multiple refresh rate
  130. if (isRateMultipleOf(matchInfo.m_refreshRate, candidate->m_refreshRate, false))
  131. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_REFRESH_RATE_MULTIPLE_CLOSE;
  132. // weight interlacing
  133. if (candidate->m_interlaced == matchInfo.m_interlaced)
  134. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_INTERLACE;
  135. if (candidate->m_id == currentVideoMode->m_id)
  136. weights[candidate->m_id]->m_weight += MATCH_WEIGHT_CURRENT;
  137. modeit++;
  138. }
  139. // now grab the mode with the highest weight
  140. DMVideoModeWeightPtr chosen;
  141. float maxWeight = 0;
  142. DMVideoModeWeightMap::const_iterator weightit = weights.constBegin();
  143. while (weightit != weights.constEnd())
  144. {
  145. QLOG_DEBUG() << "Mode " << weightit.value()->m_mode->m_id << "("
  146. << weightit.value()->m_mode->getPrettyName() << ") has weight "
  147. << weightit.value()->m_weight;
  148. if (weightit.value()->m_weight > maxWeight)
  149. {
  150. chosen = weightit.value();
  151. maxWeight = chosen->m_weight;
  152. }
  153. weightit++;
  154. }
  155. if ((chosen) && (chosen->m_weight > MATCH_WEIGHT_RES))
  156. {
  157. QLOG_INFO() << "DisplayManager RefreshMatch : found a suitable mode : "
  158. << chosen->m_mode->getPrettyName();
  159. return chosen->m_mode->m_id;
  160. }
  161. QLOG_INFO() << "DisplayManager RefreshMatch : found no suitable videomode";
  162. return -1;
  163. }
  164. ///////////////////////////////////////////////////////////////////////////////////////////////////
  165. int DisplayManager::findBestMode(int display)
  166. {
  167. int bestMode = -1;
  168. for(auto mode : m_displays[display]->m_videoModes)
  169. {
  170. if (bestMode < 0)
  171. {
  172. bestMode = mode->m_id;
  173. }
  174. else
  175. {
  176. DMVideoModePtr best = m_displays[display]->m_videoModes[bestMode];
  177. DMVideoModePtr candidate = mode;
  178. // Highest priority: prefer non-interlaced modes.
  179. if (!best->m_interlaced && candidate->m_interlaced)
  180. continue;
  181. if (best->m_bitsPerPixel > candidate->m_bitsPerPixel)
  182. continue;
  183. if (best->m_width > candidate->m_width)
  184. continue;
  185. if (best->m_height > candidate->m_height)
  186. continue;
  187. if (best->m_refreshRate > candidate->m_refreshRate)
  188. continue;
  189. bestMode = candidate->m_id;
  190. }
  191. }
  192. return bestMode;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////////////////////////
  195. int DisplayManager::getDisplayFromPoint(const QPoint& pt)
  196. {
  197. return getDisplayFromPoint(pt.x(), pt.y());
  198. }