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

Wrong z-order in scene rendererd by QQuickRenderControl

    XMLWordPrintable

Details

    • Windows

    Description

      Here, simple QQuickRenderControl using QRhi code:

      #include <QtGUi/6.6.1/QtGui/rhi/qrhi_platform.h>
      #include <QtGui/6.6.1/QtGui/rhi/qrhi.h>
      #include <QtQuickWidgets>
      
      class OffscreenRenderer : public QLabel {
      
      public:
          OffscreenRenderer()
          {
              setMinimumSize(10, 10);
              setScaledContents(true);
      
              window.setColor(Qt::transparent);
      
              QQmlComponent component{&engine, QUrl{"qrc:/App/Main.qml"}};
              item.reset(static_cast<QQuickItem *>(component.beginCreate(engine.rootContext())));
              item->setParentItem(window.contentItem());
      
              component.completeCreate();
              control.initialize();
          }
      private:
          auto resetTexture() noexcept -> void
          {
              auto rhi = control.rhi();
              const auto size = window.size();
              texture.reset(rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
              qDebug() << texture.get();
              if (!texture->create())
                  qFatal() << "failed to create texture";
              depthStencil.reset(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, 1));
              if (!depthStencil)
                  qFatal() << "failed to create depth-stencil buffer";
              QRhiTextureRenderTargetDescription desc{QRhiColorAttachment{texture.get()}, depthStencil.get()};
              rtt.reset(rhi->newTextureRenderTarget(desc));
              pass.reset(rtt->newCompatibleRenderPassDescriptor());
              rtt->setRenderPassDescriptor(pass.get());
              if (!rtt->create())
                  qFatal() << "failed to create render target";
              window.setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(rtt.get()));
          }
          auto resizeEvent(QResizeEvent *event) -> void final
          {
              window.resize(size());
              item->setSize(size());
              resetTexture();
              render();
              QLabel::resizeEvent(event);
          }
          auto render() noexcept -> void
          {
              if (!rtt)
                  return;
              control.polishItems();
              control.beginFrame();
              control.sync();
              control.render();
      
              auto rhi = control.rhi();
              QRhiReadbackResult readResult;
              QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
              readbackBatch->readBackTexture(texture.get(), &readResult);
              control.commandBuffer()->resourceUpdate(readbackBatch);
      
              control.endFrame();
      
              QImage image(reinterpret_cast<const uchar *>(readResult.data.constData()),
                           readResult.pixelSize.width(),
                           readResult.pixelSize.height(),
                           QImage::Format_RGBA8888_Premultiplied);
              setPixmap(QPixmap::fromImage(image.copy())); // detach
          }
          QQmlEngine engine;
          QQuickRenderControl control;
          QQuickWindow window{&control};
          std::unique_ptr<QQuickItem> item;
          std::unique_ptr<QRhiTexture> texture;
          std::unique_ptr<QRhiRenderBuffer> depthStencil;
          std::unique_ptr<QRhiTextureRenderTarget> rtt;
          std::unique_ptr<QRhiRenderPassDescriptor> pass;
          QTimer timer;
      };
      
      int main(int argc, char **argv) {
          QApplication app{argc, argv};
      
          QWidget w;
          auto hbox = new QHBoxLayout;
          w.setLayout(hbox);
      
          auto renderer = new OffscreenRenderer;
          hbox->addWidget(renderer);
      
          auto qw = new QQuickWidget{&w};
          qw->setSource(QUrl{"qrc:/App/Main.qml"});
          qw->setResizeMode(QQuickWidget::SizeRootObjectToView);
          hbox->addWidget(qw);
      
          w.resize(800, 400);
          w.show();
      
          return app.exec();
      }
      

      The scene Main.qml is,

      import QtQuick
      
      Item {
          id: root
      
          Rectangle {
              id: red
              anchors.fill: parent
              color: Qt.rgba(1, 0, 0, 0.3)
          }
      
          Rectangle {
              id: white
              color: 'white'
              width: parent.width * 0.2
              height: width
          }
      }
      

      So, the scene consists of two Rectangles, small white box over large red semi-transparent box.
      You can see the result in attachment(You may ignore different color tone because left one is rendered on gray background which is the default widget color).

      The left one is rendered by QQuickRenderControl and the right one is rendered by QQuickWidget which is correct.

      As you can see, the white box is rendered under red box by QQuickRenderControl which is wrong z-order.

      The result is same if you put white box as child of red box or you set z value explicitly.

      Attachments

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

        Activity

          People

            lagocs Laszlo Agocs
            bylee Byoung-young Lee
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes