DisplayManager.cpp 7.1 KB

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