Warning, /graphics/krita/3rdparty/ext_qt/0110-Pass-proper-dirty-rect-in-paint-event-to-QOpenGLWidg.patch is written in an unsupported language. File is not indexed.

0001 From f31141eb0636b94ebe90ae60a6c0b07a771769cd Mon Sep 17 00:00:00 2001
0002 From: Dmitry Kazakov <dimula73@gmail.com>
0003 Date: Thu, 3 Sep 2020 15:19:59 +0300
0004 Subject: [PATCH 27/47] Pass proper dirty rect in paint event to QOpenGLWidget
0005  with partial updates
0006 
0007 When QOpenGLWidget has partial updates enabled, there is no reason to
0008 render entire scene on every frame. Instead, the widget may rerender
0009 only a portion of it. All the data has been cached by Qt in the internal
0010 framebuffer object. This limiting is necessary when rendering a complex
0011 scene on 4k display. See https://bugs.kde.org/show_bug.cgi?id=413504
0012 
0013 The patch adds a special flag into QWidgetPrivate to notify
0014 QWidgetBackingStore that this widget needs proper tracking of
0015 the dirty region.
0016 
0017 Theoretically, flushing of the textures could also be limited to
0018 the dirty region, but it is a different task.
0019 ---
0020  src/widgets/kernel/qopenglwidget.cpp       |  1 +
0021  src/widgets/kernel/qwidget.cpp             |  1 +
0022  src/widgets/kernel/qwidget_p.h             |  1 +
0023  src/widgets/kernel/qwidgetbackingstore.cpp | 34 +++++++++++++++++-----
0024  4 files changed, 29 insertions(+), 8 deletions(-)
0025 
0026 diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
0027 index 36eae9f9db..7a0f4f2440 100644
0028 --- a/src/widgets/kernel/qopenglwidget.cpp
0029 +++ b/src/widgets/kernel/qopenglwidget.cpp
0030 @@ -1036,6 +1036,7 @@ void QOpenGLWidget::setUpdateBehavior(UpdateBehavior updateBehavior)
0031  {
0032      Q_D(QOpenGLWidget);
0033      d->updateBehavior = updateBehavior;
0034 +    d->renderToTextureWithPartialUpdates = updateBehavior == PartialUpdate;
0035  }
0036  
0037  /*!
0038 diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
0039 index 85fa2ffe39..79be7a1f88 100644
0040 --- a/src/widgets/kernel/qwidget.cpp
0041 +++ b/src/widgets/kernel/qwidget.cpp
0042 @@ -271,6 +271,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
0043        , usesDoubleBufferedGLContext(0)
0044        , mustHaveWindowHandle(0)
0045        , renderToTexture(0)
0046 +      , renderToTextureWithPartialUpdates(0)
0047        , textureChildSeen(0)
0048  #ifndef QT_NO_IM
0049        , inheritsInputMethodHints(0)
0050 diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
0051 index e541cb70e4..8c3bd88ddf 100644
0052 --- a/src/widgets/kernel/qwidget_p.h
0053 +++ b/src/widgets/kernel/qwidget_p.h
0054 @@ -772,6 +772,7 @@ public:
0055      uint usesDoubleBufferedGLContext : 1;
0056      uint mustHaveWindowHandle : 1;
0057      uint renderToTexture : 1;
0058 +    uint renderToTextureWithPartialUpdates : 1;
0059      uint textureChildSeen : 1;
0060  #ifndef QT_NO_IM
0061      uint inheritsInputMethodHints : 1;
0062 diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
0063 index d5b613a4e5..8b29a4edeb 100644
0064 --- a/src/widgets/kernel/qwidgetbackingstore.cpp
0065 +++ b/src/widgets/kernel/qwidgetbackingstore.cpp
0066 @@ -557,8 +557,14 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,
0067      const QPoint offset = widget->mapTo(tlw, QPoint());
0068  
0069      if (QWidgetPrivate::get(widget)->renderToTexture) {
0070 -        if (!widget->d_func()->inDirtyList)
0071 +        if (!widget->d_func()->inDirtyList) {
0072              addDirtyRenderToTextureWidget(widget);
0073 +            if (QWidgetPrivate::get(widget)->renderToTextureWithPartialUpdates)
0074 +                widget->d_func()->dirty = rgn;
0075 +        } else if (QWidgetPrivate::get(widget)->renderToTextureWithPartialUpdates) {
0076 +                widget->d_func()->dirty += rgn;
0077 +        }
0078 +
0079          if (!updateRequestSent || updateTime == UpdateNow)
0080              sendUpdateRequest(tlw, updateTime);
0081          return;
0082 @@ -646,16 +652,24 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
0083          return;
0084      }
0085  
0086 +    const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
0087 +
0088      if (QWidgetPrivate::get(widget)->renderToTexture) {
0089 -        if (!widget->d_func()->inDirtyList)
0090 +        if (!widget->d_func()->inDirtyList) {
0091              addDirtyRenderToTextureWidget(widget);
0092 +            if (QWidgetPrivate::get(widget)->renderToTextureWithPartialUpdates)
0093 +                widget->d_func()->dirty = widgetRect;
0094 +        } else if (QWidgetPrivate::get(widget)->renderToTextureWithPartialUpdates &&
0095 +                   !qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {
0096 +
0097 +                widget->d_func()->dirty += widgetRect;
0098 +        }
0099 +
0100          if (!updateRequestSent || updateTime == UpdateNow)
0101              sendUpdateRequest(tlw, updateTime);
0102          return;
0103      }
0104  
0105 -
0106 -    const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
0107      QRect translatedRect = widgetRect;
0108      if (widget != tlw)
0109          translatedRect.translate(widget->mapTo(tlw, QPoint()));
0110 @@ -1321,18 +1335,22 @@ void QWidgetBackingStore::doSync()
0111          // prevent triggering unnecessary backingstore painting when only the
0112          // OpenGL content changes. Check if we have such widgets in the special
0113          // dirty list.
0114 -        QVarLengthArray<QWidget *, 16> paintPending;
0115 +        QVarLengthArray<QPair<QWidget *, QRegion>, 16> paintPending;
0116          const int numPaintPending = dirtyRenderToTextureWidgets.count();
0117          paintPending.reserve(numPaintPending);
0118          for (int i = 0; i < numPaintPending; ++i) {
0119              QWidget *w = dirtyRenderToTextureWidgets.at(i);
0120 -            paintPending << w;
0121 +            paintPending << qMakePair(w,  w->d_func()->dirty);
0122              resetWidget(w);
0123          }
0124          dirtyRenderToTextureWidgets.clear();
0125          for (int i = 0; i < numPaintPending; ++i) {
0126 -            QWidget *w = paintPending[i];
0127 -            w->d_func()->sendPaintEvent(w->rect());
0128 +            QWidget *w = paintPending[i].first;
0129 +            const QRegion dirtyRegion = paintPending[i].second.isEmpty() ? QRegion(w->rect()) : paintPending[i].second;
0130 +
0131 +            w->d_func()->sendPaintEvent(dirtyRegion);
0132 +
0133 +
0134              if (w != tlw) {
0135                  QWidget *npw = w->nativeParentWidget();
0136                  if (hasPlatformWindow(w) || (npw && npw != tlw)) {
0137 -- 
0138 2.20.1.windows.1
0139