Ticket #13618: dpi6.diff

File dpi6.diff, 19.1 KB (added by Mark Kendall, 4 years ago)
  • mythtv/libs/libmythtv/mythvideoout.cpp

    diff --git a/mythtv/libs/libmythtv/mythvideoout.cpp b/mythtv/libs/libmythtv/mythvideoout.cpp
    index ee4b759d81..888b283cfc 100644
    a b void MythVideoOutput::InitDisplayMeasurements(void) 
    10201020        .arg(displayaspect).arg(source));
    10211021
    10221022    // Get the window and screen resolutions
    1023     QSize window = m_window.GetWindowRect().size();
     1023    QSize window = m_window.GetRawWindowRect().size();
    10241024    QSize screen = m_display->GetResolution();
    10251025
    10261026    // If not running fullscreen, adjust for window size and ignore any video
  • mythtv/libs/libmythtv/videooutwindow.cpp

    diff --git a/mythtv/libs/libmythtv/videooutwindow.cpp b/mythtv/libs/libmythtv/videooutwindow.cpp
    index af8af15c31..7bd5ca4929 100644
    a b  
    3838
    3939#define LOC QString("VideoWin: ")
    4040
     41
     42#define SCALED_RECT(SRC, SCALE) QRect{ static_cast<int>(SRC.left()   * SCALE), \
     43                                       static_cast<int>(SRC.top()    * SCALE), \
     44                                       static_cast<int>(SRC.width()  * SCALE), \
     45                                       static_cast<int>(SRC.height() * SCALE) }
    4146static float fix_aspect(float raw);
    4247static float snap(float value, float snapto, float diff);
    4348
    void VideoOutWindow::ScreenChanged(QScreen */*screen*/) 
    6368    MoveResize();
    6469}
    6570
     71void VideoOutWindow::PhysicalDPIChanged(qreal /*DPI*/)
     72{
     73    PopulateGeometry();
     74    m_windowRect = m_displayVisibleRect = SCALED_RECT(m_rawWindowRect, m_devicePixelRatio);
     75    MoveResize();
     76}
     77
    6678void VideoOutWindow::PopulateGeometry(void)
    6779{
    6880    if (!m_display)
    void VideoOutWindow::PopulateGeometry(void) 
    7284    if (!screen)
    7385        return;
    7486
     87#ifdef Q_OS_MAC
     88    m_devicePixelRatio = screen->devicePixelRatio();
     89#endif
     90
    7591    if (MythDisplay::SpanAllScreens() && MythDisplay::GetScreenCount() > 1)
    7692    {
    7793        m_screenGeometry = screen->virtualGeometry();
    bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, 
    416432    {
    417433        m_display = Display;
    418434        connect(m_display, &MythDisplay::CurrentScreenChanged, this, &VideoOutWindow::ScreenChanged);
     435#ifdef Q_OS_MAC
     436        connect(m_display, &MythDisplay::PhysicalDPIChanged,   this, &VideoOutWindow::PhysicalDPIChanged);
     437#endif
    419438    }
    420439
    421440    if (m_display)
    bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, 
    429448
    430449    // N.B. we are always confined to the window size so use that for the initial
    431450    // displayVisibleRect
    432     m_windowRect = m_displayVisibleRect = WindowRect;
     451    m_rawWindowRect = WindowRect;
     452    m_windowRect = m_displayVisibleRect = SCALED_RECT(WindowRect, m_devicePixelRatio);
    433453
    434454    int pbp_width = m_displayVisibleRect.width() / 2;
    435455    if (m_pipState == kPBPLeft || m_pipState == kPBPRight)
    void VideoOutWindow::SetDisplayAspect(float DisplayAspect) 
    613633
    614634void VideoOutWindow::SetWindowSize(QSize Size)
    615635{
    616     if (Size != m_windowRect.size())
     636    if (Size != m_rawWindowRect.size())
    617637    {
    618         QRect rect(m_windowRect.topLeft(), Size);
     638        QRect rect(m_rawWindowRect.topLeft(), Size);
    619639        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("New window rect: %1x%2+%3+%4")
    620640            .arg(rect.width()).arg(rect.height()).arg(rect.left()).arg(rect.top()));
    621         m_windowRect = m_displayVisibleRect = rect;
     641        m_rawWindowRect = rect;
     642        m_windowRect = m_displayVisibleRect = SCALED_RECT(rect, m_devicePixelRatio);
    622643        MoveResize();
    623644    }
    624645}
  • mythtv/libs/libmythtv/videooutwindow.h

    diff --git a/mythtv/libs/libmythtv/videooutwindow.h b/mythtv/libs/libmythtv/videooutwindow.h
    index 9480045c92..cce077b5fd 100644
    a b class VideoOutWindow : public QObject 
    4545
    4646  public slots:
    4747    void ScreenChanged          (QScreen *screen);
     48    void PhysicalDPIChanged     (qreal  /*DPI*/);
    4849
    4950    // Sets
    5051    void InputChanged           (const QSize &VideoDim, const QSize &VideoDispDim, float Aspect);
    class VideoOutWindow : public QObject 
    7475    float    GetOverridenVideoAspect(void) const { return m_videoAspectOverride;}
    7576    QRect    GetDisplayVisibleRect(void)   const { return m_displayVisibleRect; }
    7677    QRect    GetWindowRect(void)           const { return m_windowRect; }
     78    QRect    GetRawWindowRect(void)        const { return m_rawWindowRect; }
    7779    QRect    GetScreenGeometry(void)       const { return m_screenGeometry; }
    7880    QRect    GetVideoRect(void)            const { return m_videoRect; }
    7981    QRect    GetDisplayVideoRect(void)     const { return m_displayVideoRect; }
    class VideoOutWindow : public QObject 
    115117    bool    m_dbScalingAllowed {true};  ///< disable this to prevent overscan/underscan
    116118    bool    m_dbUseGUISize     {false}; ///< Use the gui size for video window
    117119    QRect   m_screenGeometry   {0,0,1024,768}; ///< Full screen geometry
     120    qreal   m_devicePixelRatio {1.0};
    118121
    119122    // Manual Zoom
    120123    float   m_manualVertScale  {1.0F}; ///< Manually applied vertical scaling.
    class VideoOutWindow : public QObject 
    147150    QRect   m_displayVisibleRect {0,0,0,0};
    148151    /// Rectangle describing QWidget bounds.
    149152    QRect   m_windowRect {0,0,0,0};
     153    /// Rectangle describing QWidget bounds - not adjusted for high DPI scaling (macos)
     154    QRect   m_rawWindowRect {0,0,0,0};
    150155    /// Used to save the display_visible_rect for
    151156    /// restoration after video embedding ends.
    152157    QRect   m_tmpDisplayVisibleRect {0,0,0,0};
  • mythtv/libs/libmythui/opengl/mythpainteropengl.cpp

    diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp b/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp
    index 8fec14d3c2..5ea9e503b1 100644
    a b void MythOpenGLPainter::Begin(QPaintDevice *Parent) 
    109109            buf = m_render->CreateVBO(static_cast<int>(MythRenderOpenGL::kVertexSize));
    110110    }
    111111
     112    // check for high dpi on macos
     113    // If we do not have swap control (i.e. OSD), then the master should be pixel
     114    // ratio 'aware' (i.e. the video output classes)
     115#ifdef Q_OS_MAC
     116    m_pixelRatio = m_swapControl ? m_parent->devicePixelRatioF() : 1.0;
     117#endif
     118    QSize currentsize = m_parent->size() * m_pixelRatio;
     119
    112120    // check if we need to adjust cache sizes
    113     if (m_lastSize != m_parent->size())
     121    if (m_lastSize != currentsize)
    114122    {
    115123        // This will scale the cache depending on the resolution in use
    116124        static const int s_onehd = 1920 * 1080;
    117125        static const int s_basesize = 64;
    118         m_lastSize = m_parent->size();
     126        m_lastSize = currentsize;
    119127        float hdscreens = (static_cast<float>(m_lastSize.width() + 1) * m_lastSize.height()) / s_onehd;
    120128        int cpu = qMax(static_cast<int>(hdscreens * s_basesize), s_basesize);
    121129        int gpu = cpu * 3 / 2;
    void MythOpenGLPainter::Begin(QPaintDevice *Parent) 
    131139    if (m_target || m_swapControl)
    132140    {
    133141        m_render->BindFramebuffer(m_target);
    134         m_render->SetViewPort(QRect(0, 0, m_parent->width(), m_parent->height()));
     142        m_render->SetViewPort(QRect(0, 0, m_lastSize.width(), m_lastSize.height()));
    135143        m_render->SetBackground(0, 0, 0, 0);
    136144        m_render->ClearFramebuffer();
    137145    }
    void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, 
    226234{
    227235    if (m_render)
    228236    {
    229         // Drawing an image  multiple times with the same VBO will stall most GPUs as
     237#ifdef Q_OS_MAC
     238        QRect dest { static_cast<int>(Dest.left()   * m_pixelRatio),
     239                     static_cast<int>(Dest.top()    * m_pixelRatio),
     240                     static_cast<int>(Dest.width()  * m_pixelRatio),
     241                     static_cast<int>(Dest.height() * m_pixelRatio) };
     242#endif
     243        // Drawing an image multiple times with the same VBO will stall most GPUs as
    230244        // the VBO is re-mapped whilst still in use. Use a pooled VBO instead.
    231245        MythGLTexture *texture = GetTextureFromCache(Image);
    232246        if (texture && m_mappedTextures.contains(texture))
    void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, 
    234248            QOpenGLBuffer *vbo = texture->m_vbo;
    235249            texture->m_vbo = m_mappedBufferPool[m_mappedBufferPoolIdx];
    236250            texture->m_destination = QRect();
    237             m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha);
     251#ifdef Q_OS_MAC
     252            m_render->DrawBitmap(texture, m_target, Source, dest, nullptr, Alpha, m_pixelRatio);
     253#else
     254            m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha, m_pixelRatio);
     255#endif
    238256            texture->m_destination = QRect();
    239257            texture->m_vbo = vbo;
    240258            if (++m_mappedBufferPoolIdx >= MAX_BUFFER_POOL)
    void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, 
    242260        }
    243261        else
    244262        {
    245             m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha);
     263#ifdef Q_OS_MAC
     264            m_render->DrawBitmap(texture, m_target, Source, dest, nullptr, Alpha, m_pixelRatio);
     265#else
     266            m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha, m_pixelRatio);
     267#endif
    246268            m_mappedTextures.append(texture);
    247269        }
    248270    }
    249271}
    250272
     273/*! \brief Render a rectangle to the UI
     274 *
     275 * \note MythRenderOpenGL can only handle simple (i.e. solid) brush patterns -
     276 * otherwise we fallback to QPainter rendering, which will create a QImage that
     277 * will be rendered as a texture.
     278 * \note Fallback to QPainter rendering for high DPI (pixel ratio > 1.0) rather
     279 * than handle the various adjustments that are needed.
     280*/
    251281void MythOpenGLPainter::DrawRect(const QRect &Area, const QBrush &FillBrush,
    252282                                 const QPen &LinePen, int Alpha)
    253283{
    254     if ((FillBrush.style() == Qt::SolidPattern ||
    255          FillBrush.style() == Qt::NoBrush) && m_render)
     284    if ((FillBrush.style() == Qt::SolidPattern || FillBrush.style() == Qt::NoBrush) &&
     285        (m_pixelRatio == 1.0) && m_render)
    256286    {
    257287        m_render->DrawRect(m_target, Area, FillBrush, LinePen, Alpha);
    258288        return;
    259289    }
     290
    260291    MythPainter::DrawRect(Area, FillBrush, LinePen, Alpha);
    261292}
    262293
    void MythOpenGLPainter::DrawRoundRect(const QRect &Area, int CornerRadius, 
    264295                                      const QBrush &FillBrush,
    265296                                      const QPen &LinePen, int Alpha)
    266297{
    267     if ((FillBrush.style() == Qt::SolidPattern ||
    268          FillBrush.style() == Qt::NoBrush) && m_render)
     298    if ((FillBrush.style() == Qt::SolidPattern || FillBrush.style() == Qt::NoBrush) &&
     299        (m_pixelRatio = 1.0) && m_render)
    269300    {
    270         m_render->DrawRoundRect(m_target, Area, CornerRadius, FillBrush,
    271                                   LinePen, Alpha);
     301        m_render->DrawRoundRect(m_target, Area, CornerRadius, FillBrush, LinePen, Alpha);
    272302        return;
    273303    }
     304
    274305    MythPainter::DrawRoundRect(Area, CornerRadius, FillBrush, LinePen, Alpha);
    275306}
    276307
  • mythtv/libs/libmythui/opengl/mythpainteropengl.h

    diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.h b/mythtv/libs/libmythui/opengl/mythpainteropengl.h
    index 097577231f..b4a72bd586 100644
    a b class MUI_PUBLIC MythOpenGLPainter : public MythPainter 
    6060    QOpenGLFramebufferObject* m_target { nullptr };
    6161    bool              m_swapControl { true };
    6262    QSize             m_lastSize { };
     63    qreal             m_pixelRatio { 1.0 };
    6364
    6465    QMap<MythImage *, MythGLTexture*> m_imageToTextureMap;
    6566    std::list<MythImage *>     m_ImageExpireList;
  • mythtv/libs/libmythui/opengl/mythrenderopengl.cpp

    diff --git a/mythtv/libs/libmythui/opengl/mythrenderopengl.cpp b/mythtv/libs/libmythui/opengl/mythrenderopengl.cpp
    index e34320f3dc..0067a0e766 100644
    a b void MythRenderOpenGL::ClearFramebuffer(void) 
    804804
    805805void MythRenderOpenGL::DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target,
    806806                                  const QRect &Source, const QRect &Destination,
    807                                   QOpenGLShaderProgram *Program, int Alpha)
     807                                  QOpenGLShaderProgram *Program, int Alpha, qreal Scale)
    808808{
    809809    makeCurrent();
    810810
    void MythRenderOpenGL::DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObje 
    827827
    828828    QOpenGLBuffer* buffer = Texture->m_vbo;
    829829    buffer->bind();
    830     if (UpdateTextureVertices(Texture, Source, Destination, 0))
     830    if (UpdateTextureVertices(Texture, Source, Destination, 0, Scale))
    831831    {
    832832        if (m_extraFeaturesUsed & kGLBufferMap)
    833833        {
    QStringList MythRenderOpenGL::GetDescription(void) 
    12621262}
    12631263
    12641264bool MythRenderOpenGL::UpdateTextureVertices(MythGLTexture *Texture, const QRect &Source,
    1265                                              const QRect &Destination, int Rotation)
     1265                                             const QRect &Destination, int Rotation, qreal Scale)
    12661266{
    12671267    if (!Texture || (Texture && Texture->m_size.isEmpty()))
    12681268        return false;
    bool MythRenderOpenGL::UpdateTextureVertices(MythGLTexture *Texture, const QRect 
    13011301    data[4 + TEX_OFFSET] = data[6 + TEX_OFFSET];
    13021302    data[5 + TEX_OFFSET] = data[1 + TEX_OFFSET];
    13031303
    1304     width  = Texture->m_crop ? min(width, Destination.width())   : Destination.width();
    1305     height = Texture->m_crop ? min(height, Destination.height()) : Destination.height();
     1304    width  = Texture->m_crop ? min(static_cast<int>(width * Scale),  Destination.width())  : Destination.width();
     1305    height = Texture->m_crop ? min(static_cast<int>(height * Scale), Destination.height()) : Destination.height();
    13061306
    13071307    data[2] = data[0] = Destination.left();
    13081308    data[5] = data[1] = Destination.top();
  • mythtv/libs/libmythui/opengl/mythrenderopengl.h

    diff --git a/mythtv/libs/libmythui/opengl/mythrenderopengl.h b/mythtv/libs/libmythui/opengl/mythrenderopengl.h
    index 199f0d642b..2ccb9a60d5 100644
    a b class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, public QOpenGLFunctio 
    143143
    144144    void  DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target,
    145145                     const QRect &Source, const QRect &Destination,
    146                      QOpenGLShaderProgram *Program, int Alpha = 255);
     146                     QOpenGLShaderProgram *Program, int Alpha = 255, qreal Scale = 1.0);
    147147    void  DrawBitmap(MythGLTexture **Textures, uint TextureCount,
    148148                     QOpenGLFramebufferObject *Target,
    149149                     const QRect &Source, const QRect &Destination,
    class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, public QOpenGLFunctio 
    171171    void  SetMatrixView(void);
    172172    void  DeleteFramebuffers(void);
    173173    static bool UpdateTextureVertices(MythGLTexture *Texture, const QRect &Source,
    174                                       const QRect &Destination, int Rotation);
     174                                      const QRect &Destination, int Rotation, qreal Scale = 1.0);
    175175    GLfloat* GetCachedVertices(GLuint Type, const QRect &Area);
    176176    void  ExpireVertices(int Max = 0);
    177177    void  GetCachedVBO(GLuint Type, const QRect &Area);
  • mythtv/libs/libmythui/platforms/mythdisplayosx.cpp

    diff --git a/mythtv/libs/libmythui/platforms/mythdisplayosx.cpp b/mythtv/libs/libmythui/platforms/mythdisplayosx.cpp
    index fa2de7c4cf..68e342a2a1 100644
    a b void MythDisplayOSX::UpdateCurrentMode(void) 
    2727    {
    2828        if (!HasMythMainWindow())
    2929        {
     30            LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot update current mode");
    3031            MythDisplay::UpdateCurrentMode();
    3132            return;
    3233        }
    void MythDisplayOSX::UpdateCurrentMode(void) 
    3637    CGDirectDisplayID disp = GetOSXDisplay(widget->winId());
    3738    if (!disp)
    3839    {
     40        LOG(VB_GENERAL, LOG_WARNING, LOC + "No display");
    3941        MythDisplay::UpdateCurrentMode();
    4042        return;
    4143    }
    4244    CGDisplayModeRef mode = CGDisplayCopyDisplayMode(disp);
    4345    if (!mode)
    4446    {
     47        LOG(VB_GENERAL, LOG_WARNING, LOC + "Could not copy mode");
    4548        MythDisplay::UpdateCurrentMode();
    4649        return;
    4750    }
    bool MythDisplayOSX::UsingVideoModes(void) 
    6770
    6871const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void)
    6972{
    70     if (!m_videoModes.empty() || !HasMythMainWindow())
     73    if (!m_videoModes.empty())
    7174        return m_videoModes;
    7275
     76    if (!HasMythMainWindow())
     77    {
     78        LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot retrieve modes");
     79        return m_videoModes;
     80    }
     81
    7382    ClearModes();
    7483
    7584    WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
    const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) 
    8392    DisplayModeMap screen_map;
    8493    CGSize sizemm = CGDisplayScreenSize(disp);
    8594
     95    LOG(VB_GENERAL, LOG_INFO, LOC + "Raw video mode sizes:");
    8696    for (int i = 0; i < CFArrayGetCount(modes); ++i)
    8797    {
    8898        CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
    const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) 
    90100        bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag;
    91101        int width       = static_cast<int>(CGDisplayModeGetWidth(mode));
    92102        int height      = static_cast<int>(CGDisplayModeGetHeight(mode));
     103        int widthp      = static_cast<int>(CGDisplayModeGetPixelWidth(mode));
     104        int heightp     = static_cast<int>(CGDisplayModeGetPixelHeight(mode));
     105
     106        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Resolution: %1x%2 PixelSize: %3x%4")
     107            .arg(width).arg(height).arg(widthp).arg(heightp));
    93108
    94109        // See note in MythDisplayX11
    95110        if (interlaced)
    const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void) 
    120135bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate)
    121136{
    122137    if (!HasMythMainWindow())
     138    {
     139        LOG(VB_GENERAL, LOG_WARNING, LOC + "Cannot switch mode");
    123140        return false;
     141    }
     142
    124143    WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
    125144    CGDirectDisplayID disp = GetOSXDisplay(win);
    126145    if (!disp)
     146    {
     147        LOG(VB_GENERAL, LOG_WARNING, LOC + "No display");
    127148        return false;
     149    }
    128150
    129151    auto rate = static_cast<double>(NAN);
    130152    MythDisplayMode desired(Size, QSize(0, 0), -1.0, DesiredRate);
    bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate) 
    147169    CGDisplayConfigRef cfg;
    148170    CGBeginDisplayConfiguration(&cfg);
    149171    CGConfigureDisplayFadeEffect(cfg, 0.3f, 0.5f, 0, 0, 0);
    150     CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr);
    151     CGError err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly);
     172    CGError err = CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr);
     173    if (err != kCGErrorSuccess)
     174        LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to set display mode (%1)").arg(err));
     175    err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly);
    152176    CGDisplayRelease(disp);
    153177    return err == kCGErrorSuccess;
    154178}