示例#1
0
const DisplayResVector& DisplayResX::GetVideoModes(void) const
{
    if (!m_videoModes.empty())
        return m_videoModes;

    MythXDisplay *display = NULL;

    XRRScreenConfiguration *cfg = GetScreenConfig(display);

    if (!cfg)
        return m_videoModes;

    int num_sizes, num_rates;

    XRRScreenSize *sizes = NULL;

    sizes = XRRConfigSizes(cfg, &num_sizes);

    for (int i = 0; i < num_sizes; ++i)
    {
        short *rates = NULL;
        rates = XRRRates(display->GetDisplay(), display->GetScreen(),
                         i, &num_rates);
        DisplayResScreen scr(sizes[i].width, sizes[i].height,
                             sizes[i].mwidth, sizes[i].mheight,
                             rates, num_rates);
        m_videoModes.push_back(scr);
    }

    t_screenrate screenmap;

    int nvidiarate = GetNvidiaRates(screenmap);

    if (nvidiarate > 0)
    {
        // Update existing DisplayResScreen vector, and update it with
        // new frequencies
        for (uint i = 0; i < m_videoModes.size(); i++)
        {
            DisplayResScreen scr = m_videoModes[i];
            int w = scr.Width();
            int h = scr.Height();
            int mw = scr.Width_mm();
            int mh = scr.Height_mm();
            std::vector<double> newrates;
            std::map<double, short> realRates;
            const std::vector<double>& rates = scr.RefreshRates();
            bool found = false;

            for (std::vector<double>::const_iterator it = rates.begin();
                    it !=  rates.end(); ++it)
            {
                uint64_t key = DisplayResScreen::CalcKey(w, h, *it);

                if (screenmap.find(key) != screenmap.end())
                {
                    // Rate is defined in NV-CONTROL extension, use it
                    newrates.push_back(screenmap[key]);
                    realRates[screenmap[key]] = (int) round(*it);
                    found = true;
#if 0
                    LOG(VB_PLAYBACK, LOG_INFO,
                        QString("CustomRate Found, set %1x%2@%3 as %4Hz")
                        .arg(w) .arg(h) .arg(*it) .arg(screenmap[key]));
#endif
                }
            }

            if (found)
            {
                m_videoModes.erase(m_videoModes.begin() + i);
                std::sort(newrates.begin(), newrates.end());
                m_videoModes.insert(m_videoModes.begin() + i,
                                    DisplayResScreen(w, h, mw, mh, newrates,
                                                     realRates));
            }
        }
    }

    m_videoModesUnsorted = m_videoModes;

    std::sort(m_videoModes.begin(), m_videoModes.end());
    XRRFreeScreenConfigInfo(cfg);
    delete display;

    return m_videoModes;
}
int DisplayResScreen::FindBestMatch(const DisplayResVector& dsr,
                                    const DisplayResScreen& d,
                                    double& target_rate)
{
    double videorate = d.RefreshRate();
    bool rate2x = false;
    bool end = false;

    // We will give priority to refresh rates that are twice what is looked for
    if ((videorate > 24.5) && (videorate < 30.5))
    {
        rate2x = true;
        videorate *= 2.0;
    }

    // Amend vector with custom list
    for (uint i=0; i<dsr.size(); ++i)
    {
        if (dsr[i].Width()==d.Width() && dsr[i].Height()==d.Height())
        {
            const std::vector<double>& rates = dsr[i].RefreshRates();
            if (rates.size() && videorate != 0)
            {
                while (!end)
                {
                    for (double precision = 0.001;
                         precision < 1.0;
                         precision *= 10.0)
                    {
                        for (uint j=0; j < rates.size(); ++j)
                        {
                            // Multiple of target_rate will do
                            if (compare_rates(videorate,rates[j], precision) ||
                                (fabs(videorate - fmod(rates[j],videorate))
                                 <= precision) ||
                                (fmod(rates[j],videorate) <= precision))
                            {
                                target_rate = rates[j];
                                return i;
                            }
                        }
                    }
                    // Can't find exact frame rate, so try rounding to the
                    // nearest integer, so 23.97Hz will work with 24Hz etc
                    for (double precision = 0.01;
                         precision < 2.0;
                         precision *= 10.0)
                    {
                        double rounded = round(videorate);
                        for (uint j=0; j < rates.size(); ++j)
                        {
                            // Multiple of target_rate will do
                            if (compare_rates(rounded,rates[j], precision) ||
                                (fabs(rounded - fmod(rates[j],rounded))
                                 <= precision) ||
                                (fmod(rates[j],rounded) <= precision))
                            {
                                target_rate = rates[j];
                                return i;
                            }
                        }
                    }
                    if (rate2x)
                    {
                        videorate /= 2.0;
                        rate2x = false;
                    }
                    else
                        end = true;
                }
                target_rate = rates[rates.size() - 1];
            }
            return i;
        }
    }
    return -1;
}