Combination QQuickFramebufferObject+texturing+GridView doesn’t show items when you scroll to them

Home / qt / Combination QQuickFramebufferObject+texturing+GridView doesn’t show items when you scroll to them

Question:
What I’m doing, in short:Deriving class MyItem from QQuickFramebufferObject. Drawing a simple textured triangle MyItem. The texture is taken from a QML item.
Wrapping MyItem in a MyItemWrapper.qml component. On Component.onCompleted:, I make a delay and then call myItem.update()
I have a scrollable (with the mouse wheel) GridView of MyItemWrapper items

The items that are initially in the viewport show fine. But when I scroll down, the items that come into the viewport don’t show at all. They only show when I hover them, since I’ve added a test MouseArea.onEntered that calls myItem.update(). I’ve observed this with 2 different systems with different GPUs.

I’ve tried enabling OpenGL debug logging for this testcase, but it prints no errors.

I’ve tried setting cacheBuffer: Number.MAX_SAFE_INTEGER on the GridView, to no avail.

Any ideas?

My code:
main.cpp:#include
#include
#include "myitem.h"

int main(int argc, char** argv) {
qmlRegisterType("MyItem", 1, 0, "MyItem");

QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
myitem.cpp:#include "myitem.h"

#include
#include
#include
#include
#include
#include
#include "mesh.h"

class MyItemRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions {
public:MyItemRenderer() {
initializeOpenGLFunctions();

m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/flat.vert.glsl");
m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/flat.frag.glsl");
m_program.bind();
m_program.bindAttributeLocation("aPos", Mesh::posAttribLocation);
m_program.link();
m_program.setUniformValue("uTex", 0);
}

void synchronize(QQuickFramebufferObject* qqfbo){
auto item = (MyItem*)qqfbo;

m_window = item->window();
m_tex = item->sourceItem()->textureProvider()->texture();
}

QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
return new QOpenGLFramebufferObject(size, format);
}

void render() {
glDisable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);

m_program.bind();
m_mesh.vao.bind();

glActiveTexture(GL_TEXTURE0);
m_tex->bind();
glDrawArrays(GL_TRIANGLES, 0, 3);

m_window->resetOpenGLState();
}

private:QQuickWindow* m_window;
Mesh m_mesh;
QSGTexture* m_tex;
QOpenGLShaderProgram m_program;
};

QQuickFramebufferObject::Renderer *MyItem::createRenderer() const {
return new MyItemRenderer();
}
myitem.h:#ifndef MYITEM_H
#define MYITEM_H

#include
#include "propertyhelper.h" // this file is from http://syncor.blogspot.bg/2014/11/qt-auto-property.html

class MyItem : public QQuickFramebufferObject {
Q_OBJECT

AUTO_PROPERTY(QQuickItem*, sourceItem)

public:Renderer *createRenderer() const;
};

#endif
mesh.h
#ifndef MESH_H
#define MESH_H

#include
#include
#include

class Mesh : protected QOpenGLFunctions {
template
int getNumBytes(std::vector vec) {
return vec.size() * sizeof(T);
}

public:Mesh(): vertexPosBuffer(QOpenGLBuffer::VertexBuffer)
{
initializeOpenGLFunctions();

std::vector vertexPosData {
0.0, 0.0,
1.0, 0.0,
1.0, 1.0
};

vao.create();
QOpenGLVertexArrayObject::Binder binder(&vao);

vertexPosBuffer.create();
vertexPosBuffer.bind();
vertexPosBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
vertexPosBuffer.allocate(vertexPosData.data(), getNumBytes(vertexPosData));

glEnableVertexAttribArray(posAttribLocation);
vertexPosBuffer.bind();
glVertexAttribPointer(posAttribLocation, 2, GL_FLOAT, false, 0, 0);
}

QOpenGLBuffer vertexPosBuffer;
QOpenGLVertexArrayObject vao;

static const int posAttribLocation = 1;
};

#endif // MESH_H
main.qml:import QtQuick 2.5
import QtQuick.Window 2.2

Window {
visible: true
id: window
width: 700
height: 700
GridView {
id: grid
anchors.fill: parent
cellWidth: 350
cellHeight: 350
model: 20
delegate: MyItemWrapper { }
}
}
MyItemWrapper.qml:import QtQuick 2.5
import MyItem 1.0

Item {
width: grid.cellWidth
height: grid.cellHeight
Rectangle {
id: texSource
x: -10000
layer.enabled: true

color: "red"
width: 100
height: 100
}

MyItem {
anchors.fill: parent

id: myItem
sourceItem: texSource
}

MouseArea {
id: mouseArea
hoverEnabled: true
anchors.fill: parent

onEntered: {
myItem.update();
}
}

function connectSingleShot(sig, slot) {
var f = function() {
slot.apply(this, arguments)
sig.disconnect(f)
}
sig.connect(f)
}

Component.onCompleted: {
connectSingleShot(window.afterRendering, function() {
myItem.update();
});
}
}
flat.frag.glsl:#version 150

in highp vec2 vTexCoord;
out vec4 outputColor;
uniform sampler2D uTex;

void main() {
outputColor = texture(uTex, vTexCoord);
}
flat.vert.glsl:#version 150

in highp vec2 aPos;
out highp vec2 vTexCoord;

void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
vTexCoord = aPos * .5 + .5;
}
I think the problem is very likely related to this older problem of mine. With this in mind, I tried two things:reparent the relevant items to have parent null during the myItem.update() line, then reparent them back. This was intended to avoid the GL rendering being affected by some middleman component of the GridView. But the result was that no items were ever displayed, for some reason.
use a Connections to connect to the onVisibleChanged signal of the MyItemWrapper, and of its parent, and of it’s parent’s parents. In the signal handler I had a console.log. It never got executed.

I’ve traced the Qt code down to this point:
http://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/quick/items/qquickwindow.cpp?h=v5.9.1#n3148

Here it sets opacity=0 for culled items. I don’t know how to continue from here though.


Answer:

Read more

Leave a Reply

Your email address will not be published. Required fields are marked *