问题
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
}
}
回答1:
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.
回答2:
You have...
QOpenGLTexture tex(QOpenGLTexture::Target2D);
According to the docs that doesn't actually create the underlying texture object. I think you then need...
tex.create();
before setting the size and allocating storage. So...
QOpenGLTexture tex(QOpenGLTexture::Target2D);
if (!tex.create()) {
/*
* Take appropriate action.
*/
}
tex.setSize(100, 100);
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::Int8);
Edit 1:
Actually, looking at the code it appears that tex.allocateStorage
should allocate a texture id if necessary. However, if that fails for some reason (no current context for example) then that could be causing the problem you're seeing.
回答3:
During "allocatestorage", You are conveying opeGL driver about the texture storage format.
For the formats "GL_BGRA or GL_RGBA", OpenGL recommends "GL_UNSIGNED_BYTE",
which is in Qt ----- "QOpenGLTexture::BGRA
" (for GL_BGRA) and "QOpenGLTexture::UInt8
" (for GL_UNSIGNED_BYTE).
https://www.khronos.org/opengl/wiki/Textures_-_more
So your allocate storage function based on (openGL recommendation) should be
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::UInt8);
来源:https://stackoverflow.com/questions/42909159/qopengltextureallocatestorage-causes-gl-invalid-value-error