Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-115133

QSGBasicInternalRectangleNode does not create enough segrement for rounded corners for HiDPI

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P3: Somewhat important
    • None
    • 6.5, dev
    • Quick: SceneGraph
    • None
    • All

    Description

      Most noticeable with small rectangles, full corner radius, and HiDPI screens (or alternatively QT_SCALE_FACTOR=5 env).

      QSGBasicInternalRectangleNode (instantiated, for example, by a plain QtQuick/Rectangle QML type) does not account for Device Pixel Ratio of its render window, resulting in poor quality circles on Retina-like displays:

      (scale factor 5, QtQuick/Rectangle on top vs. Kirigami/ShadowedRectangle — a rectangle with custom shaders — on the bottom)

      The culprit is here, in QSGBasicInternalRectangleNode::updateGeometry method:

              float outerRadius = radius;
      
              // Number of segments per corner, approximately one per 3 pixels.
              int segments = qBound(3, qCeil(outerRadius * (M_PI / 6)), 18);
      

      If you change that lower bound from 3 to, say, 10, then you'll get higher quality small circles.

      But this radius thing does not account for HiDPI. even though in QQuickRectangle::updatePaintNode there's one mention of scaling:

              qreal penWidth = d->pen->width();
              if (d->pen->pixelAligned()) {
                  qreal dpr = window() ? window()->effectiveDevicePixelRatio() : 1.0;
                  penWidth = qRound(penWidth * dpr) / dpr; // Ensures integer width after dpr scaling
              }
              rectangle->setPenWidth(penWidth);
              rectangle->setAligned(false); // width rounding already done, so the Node should not do it
      

      and what's even more interesting, software rendered can access such data via QPainter API:

      void QSGSoftwareInternalRectangleNode::paint(QPainter *painter)
      {
          //We can only check for a device pixel ratio change when we know what
          //paint device is being used.
          if (!qFuzzyCompare(painter->device()->devicePixelRatio(), m_devicePixelRatio)) {
              m_devicePixelRatio = painter->device()->devicePixelRatio();
              generateCornerPixmap();
          }
      

      But I can't find anything suitable in SGNode or context classes. Maybe m_devicePixelRatio has to be uplifted from QSGSoftwareInternalRectangleNode to its parent class QSGInternalRectangleNode?

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            janichol Andy Nichols
            ratijas ivan tkachenko
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes