// // DisplayManager.cpp // konvergo // // Created by Lionel CHAZALLON on 28/09/2014. // // #include "QsLog.h" #include "DisplayManager.h" #include "math.h" /////////////////////////////////////////////////////////////////////////////////////////////////// DisplayManager::DisplayManager(QObject* parent) : QObject(parent) {} /////////////////////////////////////////////////////////////////////////////////////////////////// bool DisplayManager::initialize() { QLOG_INFO() << QString("DisplayManager found %1 Display(s).").arg(displays.size()); // list video modes foreach(int displayid, displays.keys()) { DMDisplayPtr display = displays[displayid]; QLOG_INFO() << QString("Available modes for Display #%1 (%2)").arg(displayid).arg(display->name); for (int modeid = 0; modeid < display->videoModes.size(); modeid++) { DMVideoModePtr mode = display->videoModes[modeid]; QLOG_INFO() << QString("Mode %1: %2").arg(modeid, 2).arg(mode->getPrettyName()); } } // Log current display mode int mainDisplay = getMainDisplay(); if (mainDisplay >= 0) { int currentMode = getCurrentDisplayMode(mainDisplay); if (currentMode >= 0) QLOG_INFO() << QString("DisplayManager : Current Display Mode on Display #%1 is %2") .arg(mainDisplay) .arg(displays[mainDisplay]->videoModes[currentMode]->getPrettyName()); else QLOG_ERROR() << "DisplayManager : unable to retrieve current video mode"; } else QLOG_ERROR() << "DisplayManager : unable to retrieve main display"; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////// DMVideoModePtr DisplayManager::getCurrentVideoMode(int display) { int currentMode = getCurrentDisplayMode(display); DMVideoModePtr currentVideoMode; if (currentMode >= 0) currentVideoMode = displays[display]->videoModes[currentMode]; return currentVideoMode; } /////////////////////////////////////////////////////////////////////////////////////////////////// bool DisplayManager::isValidDisplay(int display) { return displays.contains(display); } /////////////////////////////////////////////////////////////////////////////////////////////////// bool DisplayManager::isValidDisplayMode(int display, int mode) { if (isValidDisplay(display)) if (mode >= 0 && mode < displays[display]->videoModes.size()) return true; return false; } /////////////////////////////////////////////////////////////////////////////////////////////////// bool DisplayManager::isRateMultipleOf(float refresh, float multiple, bool exact) { if (((int)refresh == 0) || ((int)multiple == 0)) return false; if (((int)multiple % (int)refresh) == 0) return true; int roundedRefresh = (int)round(refresh); int roundedMultiple = (int)round(multiple); if (((roundedMultiple % roundedRefresh) == 0) && (!exact)) return true; return false; } /////////////////////////////////////////////////////////////////////////////////////////////////// int DisplayManager::findBestMatch(int display, DMMatchMediaInfo& matchInfo) { // Grab current videomode information DMVideoModePtr currentVideoMode = getCurrentVideoMode(display); if (!currentVideoMode) return -1; // now we try to find the exact match in current resolution // then fill a list DMVideoModeWeightMap weights; DMVideoModeMap::const_iterator modeit = displays[display]->videoModes.constBegin(); while (modeit != displays[display]->videoModes.constEnd()) { DMVideoModePtr candidate = modeit.value(); weights[candidate->id] = DMVideoModeWeightPtr(new DMVideoModeWeight); weights[candidate->id]->mode = candidate; weights[candidate->id]->weight = 0; // Weight Resolution match if ((candidate->width == currentVideoMode->width) && (candidate->height == currentVideoMode->height) && (candidate->bitsPerPixel == currentVideoMode->bitsPerPixel)) { weights[candidate->id]->weight += MATCH_WEIGHT_RES; } // weight refresh rate // exact Match if (candidate->refreshRate == matchInfo.refreshRate) weights[candidate->id]->weight += MATCH_WEIGHT_REFRESH_RATE_EXACT; // exact multiple refresh rate if (isRateMultipleOf(matchInfo.refreshRate, candidate->refreshRate, true)) weights[candidate->id]->weight += MATCH_WEIGHT_REFRESH_RATE_MULTIPLE; // close refresh match (less than 1 hz diff to match all 23.xxx modes to 24p) if (fabs(candidate->refreshRate - matchInfo.refreshRate) <= 0.5) { weights[candidate->id]->weight += MATCH_WEIGHT_REFRESH_RATE_CLOSE; } // approx multiple refresh rate if (isRateMultipleOf(matchInfo.refreshRate, candidate->refreshRate, false)) weights[candidate->id]->weight += MATCH_WEIGHT_REFRESH_RATE_MULTIPLE_CLOSE; // weight interlacing if (candidate->interlaced == matchInfo.interlaced) weights[candidate->id]->weight += MATCH_WEIGHT_INTERLACE; if (candidate->id == currentVideoMode->id) weights[candidate->id]->weight += MATCH_WEIGHT_CURRENT; modeit++; } // now grab the mode with the highest weight DMVideoModeWeightPtr chosen; float maxWeight = 0; DMVideoModeWeightMap::const_iterator weightit = weights.constBegin(); while (weightit != weights.constEnd()) { QLOG_DEBUG() << "Mode " << weightit.value()->mode->id << "(" << weightit.value()->mode->getPrettyName() << ") has weight " << weightit.value()->weight; if (weightit.value()->weight > maxWeight) { chosen = weightit.value(); maxWeight = chosen->weight; } weightit++; } if ((chosen) && (chosen->weight > MATCH_WEIGHT_RES)) { QLOG_INFO() << "DisplayManager RefreshMatch : found a suitable mode : " << chosen->mode->getPrettyName(); return chosen->mode->id; } QLOG_INFO() << "DisplayManager RefreshMatch : found no suitable videomode"; return -1; } /////////////////////////////////////////////////////////////////////////////////////////////////// int DisplayManager::findBestMode(int display) { int best_mode = -1; foreach (auto mode, displays[display]->videoModes) { if (best_mode < 0) { best_mode = mode->id; } else { DMVideoModePtr best = displays[display]->videoModes[best_mode]; DMVideoModePtr candidate = mode; // Highest priority: prefer non-interlaced modes. if (!best->interlaced && candidate->interlaced) continue; if (best->bitsPerPixel > candidate->bitsPerPixel) continue; if (best->width > candidate->width) continue; if (best->height > candidate->height) continue; if (best->refreshRate > candidate->refreshRate) continue; best_mode = candidate->id; } } return best_mode; } /////////////////////////////////////////////////////////////////////////////////////////////////// int DisplayManager::getDisplayFromPoint(const QPoint& pt) { return getDisplayFromPoint(pt.x(), pt.y()); }