2017-03-20 2 views
0

J'ai distillé ceci en code Qt trivial dans lequel la seule chose intéressante est plusieurs lignes dans synchronize() manipulant une texture. J'obtiens un GL_INVALID_VALUE de la ligne allocateStorage. Quelqu'un sait pourquoi? Je suppose que c'est probablement dû aux paramètres que je passe à cette fonction.QOpenGLTexture :: allocateStorage provoque l'erreur GL_INVALID_VALUE

Mon 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 
    } 
} 

Répondre

1

Après avoir regardé la source de QOpenGLTexture::createMutableTexture et QOpenGLTexture::allocateStorage() (sans argument la version) j'ai vu que deux arguments allocateStorage surcharge est vraiment, vraiment trompeuse. Les docs font croire que ses 2 arguments seront utilisés comme format interne de la texture (3ème argument de l'appel glTexImage2D dans l'implémentation), alors qu'en fait ils ne sont utilisés que comme "source-data-to-" transfer-from-system-RAM "format/type (7ème et 8ème arguments de glTexImage2D), qui, dans le cas de passer un pointeur nul à glTexImage2D, n'a pas d'importance du tout sauf dans les cas frange OpenGL ES 2.

La façon de fait demande un certain format interne pour la texture est d'appeler tex.setFormat avant d'appeler tex.allocateStorage.Donc, je l'ai remplacé mon allocateStorage ligne avec ceci:

tex.setFormat(QOpenGLTexture::RGBA8_UNorm); 
tex.allocateStorage(); 

Et corrigé l'erreur.

+0

Eh bien, pour entendre aussi l'autre cloche, les deux types enum des paramètres de 'allocateStorage' documentent clairement qu'ils concernent le format externe, pas le format interne ... – peppe

+0

Les wrappers GL de Qt sont désastreux. répondre, sinon je passerais des heures à le comprendre. Les personnes qui ont conçu cette API ne connaissent pas vraiment OpenGL: / –

0

Vous avez ...

QOpenGLTexture tex(QOpenGLTexture::Target2D); 

Selon le docs qui ne crée pas réellement l'objet de texture sous-jacent. Je pense que vous avez alors besoin ...

tex.create(); 

avant de définir la taille et d'allouer le stockage. Alors ...

QOpenGLTexture tex(QOpenGLTexture::Target2D); 
if (!tex.create()) { 

    /* 
    * Take appropriate action. 
    */ 
} 
tex.setSize(100, 100); 
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::Int8); 

Edit 1:

En fait, en regardant le code, il semble que tex.allocateStorage devrait attribuer un identifiant de texture si nécessaire. Cependant, si cela échoue pour une raison quelconque (pas de contexte actuel par exemple), alors cela pourrait être à l'origine du problème que vous voyez.

+0

Merci, mais j'ai imprimé 'tex.isCreated()' après le 'allocateStorage' et j'ai' true'. –

0

Lors de "allocatestorage", vous transmettez le pilote opeGL à propos du format de stockage de texture.

Pour les formats "GL_BGRA ou GL_RGBA", OpenGL recommande "GL_UNSIGNED_BYTE",

qui est dans Qt ----- "QOpenGLTexture::BGRA" (pour GL_BGRA) et "QOpenGLTexture::UInt8" (pour GL_UNSIGNED_BYTE).

https://www.khronos.org/opengl/wiki/Textures_-_more

Ainsi, votre allocation fonction de stockage en fonction (recommandation openGL) devrait être

tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::UInt8);