Ticket #13618: dpi8_v31.diff

File dpi8_v31.diff, 17.2 KB (added by Mark Kendall, 4 years ago)

Commit candidate - v31

  • 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..9c7326f11c 100644
    a b  
    3838
    3939#define LOC QString("VideoWin: ")
    4040
     41#define SCALED_RECT(SRC, SCALE) QRect{ static_cast<int>(SRC.left()   * SCALE), \
     42                                       static_cast<int>(SRC.top()    * SCALE), \
     43                                       static_cast<int>(SRC.width()  * SCALE), \
     44                                       static_cast<int>(SRC.height() * SCALE) }
     45
    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 will update m_devicePixelRatio
     74    PopulateGeometry();
     75    m_windowRect = m_displayVisibleRect = SCALED_RECT(m_rawWindowRect, m_devicePixelRatio);
     76    MoveResize();
     77}
     78
    6679void VideoOutWindow::PopulateGeometry(void)
    6780{
    6881    if (!m_display)
    void VideoOutWindow::PopulateGeometry(void) 
    7285    if (!screen)
    7386        return;
    7487
     88#ifdef Q_OS_MACOS
     89    m_devicePixelRatio = screen->devicePixelRatio();
     90#endif
     91
    7592    if (MythDisplay::SpanAllScreens() && MythDisplay::GetScreenCount() > 1)
    7693    {
    7794        m_screenGeometry = screen->virtualGeometry();
    bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, 
    416433    {
    417434        m_display = Display;
    418435        connect(m_display, &MythDisplay::CurrentScreenChanged, this, &VideoOutWindow::ScreenChanged);
     436#ifdef Q_OS_MACOS
     437        connect(m_display, &MythDisplay::PhysicalDPIChanged,   this, &VideoOutWindow::PhysicalDPIChanged);
     438#endif
    419439    }
    420440
    421441    if (m_display)
    bool VideoOutWindow::Init(const QSize &VideoDim, const QSize &VideoDispDim, 
    429449
    430450    // N.B. we are always confined to the window size so use that for the initial
    431451    // displayVisibleRect
    432     m_windowRect = m_displayVisibleRect = WindowRect;
     452    m_rawWindowRect = WindowRect;
     453    m_windowRect = m_displayVisibleRect = SCALED_RECT(WindowRect, m_devicePixelRatio);
    433454
    434455    int pbp_width = m_displayVisibleRect.width() / 2;
    435456    if (m_pipState == kPBPLeft || m_pipState == kPBPRight)
    void VideoOutWindow::SetDisplayAspect(float DisplayAspect) 
    613634
    614635void VideoOutWindow::SetWindowSize(QSize Size)
    615636{
    616     if (Size != m_windowRect.size())
     637    if (Size != m_rawWindowRect.size())
    617638    {
    618         QRect rect(m_windowRect.topLeft(), Size);
     639        QRect rect(m_rawWindowRect.topLeft(), Size);
    619640        LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("New window rect: %1x%2+%3+%4")
    620641            .arg(rect.width()).arg(rect.height()).arg(rect.left()).arg(rect.top()));
    621         m_windowRect = m_displayVisibleRect = rect;
     642        m_rawWindowRect = rect;
     643        m_windowRect = m_displayVisibleRect = SCALED_RECT(rect, m_devicePixelRatio);
    622644        MoveResize();
    623645    }
    624646}
  • 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/mythpainter.h

    diff --git a/mythtv/libs/libmythui/mythpainter.h b/mythtv/libs/libmythui/mythpainter.h
    index b6b054a813..67175a1ed5 100644
    a b class UIEffects; 
    2929using LayoutVector = QVector<QTextLayout *>;
    3030using FormatVector = QVector<QTextLayout::FormatRange>;
    3131
    32 class MUI_PUBLIC MythPainter
     32class MUI_PUBLIC MythPainter : public QObject
    3333{
     34    Q_OBJECT
     35
    3436  public:
    3537    MythPainter();
    3638    /** MythPainter destructor.
  • mythtv/libs/libmythui/opengl/mythpainteropengl.cpp

    diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp b/mythtv/libs/libmythui/opengl/mythpainteropengl.cpp
    index 8fec14d3c2..abbb7685f0 100644
    a b MythOpenGLPainter::MythOpenGLPainter(MythRenderOpenGL *Render, QWidget *Parent) 
    2020
    2121    if (!m_render)
    2222        LOG(VB_GENERAL, LOG_ERR, "OpenGL painter has no render device");
     23
     24#ifdef Q_OS_MACOS
     25     m_display = MythDisplay::AcquireRelease();
     26     CurrentDPIChanged(m_parent->devicePixelRatioF());
     27     connect(m_display, &MythDisplay::CurrentDPIChanged, this, &MythOpenGLPainter::CurrentDPIChanged);
     28#endif
    2329}
    2430
    2531MythOpenGLPainter::~MythOpenGLPainter()
    2632{
     33#ifdef Q_OS_MACOS
     34    MythDisplay::AcquireRelease(false);
     35#endif
     36
    2737    if (!m_render)
    2838        return;
    2939    if (!m_render->IsReady())
    void MythOpenGLPainter::ClearCache(void) 
    8494    m_imageToTextureMap.clear();
    8595}
    8696
     97void MythOpenGLPainter::CurrentDPIChanged(qreal DPI)
     98{
     99    m_pixelRatio = DPI;
     100    m_usingHighDPI = !qFuzzyCompare(m_pixelRatio, 1.0);
     101    LOG(VB_GENERAL, LOG_INFO, QString("High DPI scaling %1").arg(m_usingHighDPI ? "enabled" : "disabled"));
     102}
     103
    87104void MythOpenGLPainter::Begin(QPaintDevice *Parent)
    88105{
    89106    MythPainter::Begin(Parent);
    void MythOpenGLPainter::Begin(QPaintDevice *Parent) 
    109126            buf = m_render->CreateVBO(static_cast<int>(MythRenderOpenGL::kVertexSize));
    110127    }
    111128
     129    QSize currentsize = m_parent->size();
     130
    112131    // check if we need to adjust cache sizes
    113     if (m_lastSize != m_parent->size())
     132    // NOTE - don't use the scaled size if using high DPI. Our images are at the lower
     133    // resolution
     134    if (m_lastSize != currentsize)
    114135    {
    115136        // This will scale the cache depending on the resolution in use
    116137        static const int s_onehd = 1920 * 1080;
    117138        static const int s_basesize = 64;
    118         m_lastSize = m_parent->size();
     139        m_lastSize = currentsize;
    119140        float hdscreens = (static_cast<float>(m_lastSize.width() + 1) * m_lastSize.height()) / s_onehd;
    120141        int cpu = qMax(static_cast<int>(hdscreens * s_basesize), s_basesize);
    121142        int gpu = cpu * 3 / 2;
    void MythOpenGLPainter::Begin(QPaintDevice *Parent) 
    130151
    131152    if (m_target || m_swapControl)
    132153    {
     154        // If we are master and using high DPI then scale the viewport
     155        if (m_swapControl && m_usingHighDPI)
     156            currentsize *= m_pixelRatio;
    133157        m_render->BindFramebuffer(m_target);
    134         m_render->SetViewPort(QRect(0, 0, m_parent->width(), m_parent->height()));
     158        m_render->SetViewPort(QRect(0, 0, currentsize.width(), currentsize.height()));
    135159        m_render->SetBackground(0, 0, 0, 0);
    136160        m_render->ClearFramebuffer();
    137161    }
    MythGLTexture* MythOpenGLPainter::GetTextureFromCache(MythImage *Image) 
    221245    return texture;
    222246}
    223247
     248#ifdef Q_OS_MACOS
     249#define DEST dest
     250#else
     251#define DEST Dest
     252#endif
     253
    224254void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image,
    225255                                  const QRect &Source, int Alpha)
    226256{
    227257    if (m_render)
    228258    {
    229         // Drawing an image  multiple times with the same VBO will stall most GPUs as
     259#ifdef Q_OS_MACOS
     260        QRect dest = QRect(static_cast<int>(Dest.left()   * m_pixelRatio),
     261                           static_cast<int>(Dest.top()    * m_pixelRatio),
     262                           static_cast<int>(Dest.width()  * m_pixelRatio),
     263                           static_cast<int>(Dest.height() * m_pixelRatio));
     264#endif
     265
     266        // Drawing an image multiple times with the same VBO will stall most GPUs as
    230267        // the VBO is re-mapped whilst still in use. Use a pooled VBO instead.
    231268        MythGLTexture *texture = GetTextureFromCache(Image);
    232269        if (texture && m_mappedTextures.contains(texture))
    void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, 
    234271            QOpenGLBuffer *vbo = texture->m_vbo;
    235272            texture->m_vbo = m_mappedBufferPool[m_mappedBufferPoolIdx];
    236273            texture->m_destination = QRect();
    237             m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha);
     274            m_render->DrawBitmap(texture, m_target, Source, DEST, nullptr, Alpha, m_pixelRatio);
    238275            texture->m_destination = QRect();
    239276            texture->m_vbo = vbo;
    240277            if (++m_mappedBufferPoolIdx >= MAX_BUFFER_POOL)
    void MythOpenGLPainter::DrawImage(const QRect &Dest, MythImage *Image, 
    242279        }
    243280        else
    244281        {
    245             m_render->DrawBitmap(texture, m_target, Source, Dest, nullptr, Alpha);
     282            m_render->DrawBitmap(texture, m_target, Source, DEST, nullptr, Alpha, m_pixelRatio);
    246283            m_mappedTextures.append(texture);
    247284        }
    248285    }
    249286}
    250287
     288/*! \brief Draw a rectangle
     289 *
     290 * If it is a simple rectangle, then use our own shaders for rendering (which
     291 * saves texture memory but may not be as accurate as Qt rendering) otherwise
     292 * fallback to Qt painting to a QImage, which is uploaded as a texture.
     293 *
     294 * \note If high DPI scaling is in use, just use Qt painting rather than
     295 * handling all of the adjustments required for pen width etc etc.
     296*/
    251297void MythOpenGLPainter::DrawRect(const QRect &Area, const QBrush &FillBrush,
    252298                                 const QPen &LinePen, int Alpha)
    253299{
    254300    if ((FillBrush.style() == Qt::SolidPattern ||
    255          FillBrush.style() == Qt::NoBrush) && m_render)
     301         FillBrush.style() == Qt::NoBrush) && m_render && !m_usingHighDPI)
    256302    {
    257303        m_render->DrawRect(m_target, Area, FillBrush, LinePen, Alpha);
    258304        return;
    void MythOpenGLPainter::DrawRoundRect(const QRect &Area, int CornerRadius, 
    265311                                      const QPen &LinePen, int Alpha)
    266312{
    267313    if ((FillBrush.style() == Qt::SolidPattern ||
    268          FillBrush.style() == Qt::NoBrush) && m_render)
     314         FillBrush.style() == Qt::NoBrush) && m_render && !m_usingHighDPI)
    269315    {
    270316        m_render->DrawRoundRect(m_target, Area, CornerRadius, FillBrush,
    271317                                  LinePen, Alpha);
  • mythtv/libs/libmythui/opengl/mythpainteropengl.h

    diff --git a/mythtv/libs/libmythui/opengl/mythpainteropengl.h b/mythtv/libs/libmythui/opengl/mythpainteropengl.h
    index 097577231f..540f7db79d 100644
    a b  
    66#include <QQueue>
    77
    88// MythTV
     9#include "mythdisplay.h"
    910#include "mythpainter.h"
    1011#include "mythimage.h"
    1112
    class QOpenGLFramebufferObject; 
    2223
    2324class MUI_PUBLIC MythOpenGLPainter : public MythPainter
    2425{
     26    Q_OBJECT
     27
    2528  public:
    2629    explicit MythOpenGLPainter(MythRenderOpenGL *Render = nullptr, QWidget *Parent = nullptr);
    2730   ~MythOpenGLPainter() override;
    class MUI_PUBLIC MythOpenGLPainter : public MythPainter 
    4649    void PushTransformation(const UIEffects &Fx, QPointF Center = QPointF()) override;
    4750    void PopTransformation(void) override;
    4851
     52  public slots:
     53    void CurrentDPIChanged(qreal DPI);
     54
    4955  protected:
    5056    void  ClearCache(void);
    5157    MythGLTexture* GetTextureFromCache(MythImage *Image);
    class MUI_PUBLIC MythOpenGLPainter : public MythPainter 
    6066    QOpenGLFramebufferObject* m_target { nullptr };
    6167    bool              m_swapControl { true };
    6268    QSize             m_lastSize { };
     69    qreal             m_pixelRatio   { 1.0     };
     70    MythDisplay*      m_display      { nullptr };
     71    bool              m_usingHighDPI { false   };
    6372
    6473    QMap<MythImage *, MythGLTexture*> m_imageToTextureMap;
    6574    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..684740c584 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);