I've distilled this to trivial Qt code in which the only interesting thing is several lines in synchronize()
handling a texture. I get a GL_INVALID_VALUE from the allocateStorage
line. Anyone knows why? I suspect it's probably due to the parameters I pass to this function.
My code:
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
class MyItem : public QQuickFramebufferObject {
Q_OBJECT
public:
Renderer* createRenderer() const;
};
class MyItemRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions {
public:
MyItemRenderer() {
initializeOpenGLFunctions();
}
void render() {
}
QOpenGLFramebufferObject* createFramebufferObject(const QSize &size) {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
return new QOpenGLFramebufferObject(size, format);
}
protected:
void synchronize(QQuickFramebufferObject* qqfbo) {
Q_UNUSED(qqfbo)
QOpenGLTexture tex(QOpenGLTexture::Target2D);
tex.setSize(100, 100);
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::Int8);
qDebug() << "starting loop";
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
qDebug("\tgl error: 0x%x", err, 0, 16);
}
}
};
QQuickFramebufferObject::Renderer* MyItem::createRenderer() const {
return new MyItemRenderer();
}
int main(int argc, char **argv) {
QGuiApplication app(argc, argv);
qmlRegisterType<MyItem>("MyItem", 1, 0, "MyItem");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
#include "main.moc"
main.qml
import QtQuick 2.0
import MyItem 1.0
import QtQuick.Window 2.2
Window {
visible: true
width: 400
height: 400
MyItem {
anchors.fill: parent
}
}
After looking at the source of QOpenGLTexture::createMutableTexture
and QOpenGLTexture::allocateStorage()
(no-argument version) I saw that two-argument allocateStorage
overload is really, really misleading. The docs make it seem like its 2 args will be used as the internal format of the texture (3rd arg of the glTexImage2D
call in the implementation), when in fact they're used only as the "source-data-to-transfer-from-system-RAM" format/type (7th and 8th args of glTexImage2D
), which, in the case of passing a null pointer to glTexImage2D
, don't matter at all except in fringe OpenGL ES 2 cases.
The way to actually request a certain internal format for the texture is to call tex.setFormat
before calling tex.allocateStorage
. So I replaced my allocateStorage
line with this:
tex.setFormat(QOpenGLTexture::RGBA8_UNorm);
tex.allocateStorage();
And that fixed the error.