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

How to get the dirty areas on QtQuick

XMLWordPrintable

    • Icon: Suggestion Suggestion
    • Resolution: Invalid
    • Icon: Not Evaluated Not Evaluated
    • None
    • None
    • Quick: SceneGraph
    • None

      When i use a QSGRenderNode to custom render content, no matter where any area of the scene graph needs to be repaint, the QSGRenderNode::paint will always be called, But I need to judge whether certain operations should be performed based on the dirty area, what should I do? I have an example here, I need to do this in RenderNode::render, please check the following code:

      // dquickblitframebuffer.h
      
      #include <QQuickItem>
      
      class Q_DECL_EXPORT DQuickBlitFramebuffer : public QQuickItem
      {
      public:
          explicit DQuickBlitFramebuffer(QQuickItem *parent = nullptr);
      
      private:
          QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
      };
      
      // dquickblitframebuffer.cpp
      #include "dquickblitframebuffer.h"
      
      #include <QSGRenderNode>
      #include <QDebug>
      #include <QOpenGLContext>
      #include <QOpenGLExtraFunctions>
      
      #include <private/qquickitem_p.h>
      #include <private/qquickwindow_p.h>
      
      class Q_DECL_HIDDEN RenderNode : public QSGRenderNode {
      public:
          RenderNode(QQuickItem *item)
              : m_item(item) {}
      
          StateFlags changedStates() const override {
              return 0;
          }
          void render(const RenderState *state) override {
              ...
              // get dirty areas
              QQuickWindowPrivate windowD = QQuickWindowPrivate::get(m_item->window());
              // This is not a correct waym, the geometry of the dirty item is not equivalent to the dirty area in the scene graph.
      //        const QRegion dirtyArea = QRect(windowD.dirtyItemList->position(), windowD.dirtyItemList->size());
              QQuickItemPrivate *itemD = QQuickItemPrivate::get(m_item);
              // I need the dirty area of the scene graph when I draw this time
              const QRegion dirtyArea = itemD->sceneGraphRenderContext()->dirtyArea();
              // Convert coordinates
              const QRect rect = state->projectionMatrix()->mapRect(m_rect);
      
              if (dirtyArea.contains(rect)) {
                  ...
                  GLint old = 0;
                  QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_DRAW_FRAMEBUFFER, &old);
                  QOpenGLContext::currentContext()->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo.handle());
                  // Copy the content below yourself to a texture
                  QOpenGLContext::currentContext()->extraFunctions()->glBlitFramebuffer(rect.x(), rect.y(),
                                                                                        rect.width(), rect.height(),
                                                                                        ...);
                  // Reset
                  QOpenGLContext::currentContext()->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old);
                  // Only when the overlap areas with is dirty, we need to continue the next processing
                  ...
                  I can do Gaussian blur for the m_fbo.texture()
              }
      
              Draw the m_fbo.texture()
              ...
          }
          void releaseResources() override {
      
          }
          RenderingFlags flags() const override {
              return OpaqueRendering;
          }
          QRectF rect() const override {
              return m_rect;
          }
      
      private:
          QRectF m_rect;
          QQuickItem *m_item;
          QOpenGLFramebufferObject m_fbo;
      };
      
      DQuickBlitFramebuffer::DQuickBlitFramebuffer(QQuickItem *parent)
          : QQuickItem(parent)
      {
          setFlag(ItemHasContents);
      }
      
      QSGNode *DQuickBlitFramebuffer::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *oldData)
      {
          qDebug() << Q_FUNC_INFO;
      
          if (!oldNode) {
              return new RenderNode(this);
          }
      
          return oldNode;
      }
      
      

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

            srutledg Shawn Rutledge
            zccrs JiDe Zhang
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes