为什么销毁QOffscreenSurface子类时程序崩溃?

问题描述 投票:0回答:1

我想使用 QOffscreenSurface 和 QOpenglContext 类在屏幕外渲染纹理。这是我的代码:

OffscreenRender.h

class OffscreenRender:public QOffscreenSurface,protected QOpenGLFunctions_4_3_Core
{
    Q_OBJECT
public:
    explicit OffscreenRender(QObject *parent = 0);
    virtual ~OffscreenRender();
    void paint();
    GLuint* getTBO();
    QOpenGLContext *getCurrentContext(){return openGLContext;}
private:
    void initialGL();
private:
    bool glInitialized = false;
    QOpenGLContext *openGLContext = nullptr;
    GLuint proGen = 0,
    vaoGen = 0,
    vboGen = 0,
    tbo = 0,
    fbo = 0;
};

OffscreenRender.cpp

OffscreenRender::OffscreenRender(QObject *parent)
{
    setParent(parent);
    QSurfaceFormat surfaceFormat;
    surfaceFormat.setMajorVersion(4);
    surfaceFormat.setMinorVersion(3);
    surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);

    openGLContext = new QOpenGLContext();
    openGLContext->setFormat(surfaceFormat);
    QOpenGLContext *share = QOpenGLContext::globalShareContext();
    openGLContext->setShareContext(share);

    if(openGLContext->create()){
        setFormat(surfaceFormat);
        create();
        if(!isValid())
            qDebug("Unable to create the Offscreen surface");
            initialGL();
    }
    else{
        qDebug("Unable to create the context");
    }
}

OffscreenRender::~OffscreenRender(){
    openGLContext->makeCurrent(this);
    if(glIsProgram(proGen)){
        glDeleteProgram(proGen);
    }
    if(glIsVertexArray(vaoGen)){
        glDeleteVertexArrays(1,&vaoGen);
    }
    if(glIsBuffer(vboGen)){
        glDeleteBuffers(1,&vboGen);
    }
    if(glIsTexture(tbo)){
        glDeleteTextures(1,&tbo);
    }
    if(glIsFramebuffer(fbo)){
        glDeleteFramebuffers(1,&fbo);
    }
    openGLContext->doneCurrent();
    if(openGLContext){
        delete openGLContext;
    }
}

void OffscreenRender::paint(){
    if(glInitialized){
        openGLContext->makeCurrent(this);
        glViewport(0, 0, 100, 100);
        glClearColor(1,0,1,1);
        glUseProgram(proGen);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
        glDrawBuffer(GL_COLOR_ATTACHMENT0);
        glClear(GL_COLOR_BUFFER_BIT);
        glBindVertexArray(vaoGen);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        openGLContext->doneCurrent();
    }
}

GLuint *OffscreenRender::getTBO(){return &tbo;}

void OffscreenRender::initialGL(){
    openGLContext->makeCurrent(this);
    if(!initializeOpenGLFunctions()){
        qDebug("Unable to initialize the functions");
        return;
    }
    proGen = loadShaders();

    glGenVertexArrays(1, &vaoGen);
    glBindVertexArray(vaoGen);

    glGenBuffers(1, &vboGen);
    glBindBuffer(GL_ARRAY_BUFFER,vboGen);
    int nBytes = sizeof(float) * 16;
    glBufferData(GL_ARRAY_BUFFER,nBytes,vertexCord,GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, NULL);
    glEnableVertexAttribArray(0);

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &tbo);
    glBindTexture(GL_TEXTURE_2D, tbo);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 100, 100);

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tbo, 0);
    openGLContext->doneCurrent();
    glInitialized = true;
}

调用OffscreenRender::paint()后,该类将在纹理中心渲染一个矩形

tbo
。但是在destroy函数中,当调用
delete openGLContext;
时,Qt报告
ASSERT: "d_1_0_Core->refs.load()" in file opengl\qopenglfunctions_4_3_core.cpp, line 93
。删除此删除调用后,程序运行良好.我不知道原因。

qt opengl
1个回答
0
投票

在加载 OpenGL 函数之前,您需要有 OpenGL 上下文。当调用 OpenGL 函数加载器 (

QOpenGLFunctions_4_3_Core
) 的析构函数时,上下文必须仍然有效 - 这不会在您的代码中发生,因为:

  1. 构造函数按以下顺序调用:
    QOffscreenSurface
    QOpenGLFunctions_4_3_Core
    OffscreenRender
  2. 上下文已创建
  3. 功能已加载
  4. OffscreenRender
    上下文的析构函数中被删除
  5. 然后调用
    QOpenGLFunctions_4_3_Core
    QOffscreenSurface
    的默认析构函数

第(5)点

QOpenGLFunctions_4_3_Core
的构造函数期望加载GL函数时使用的上下文仍然有效,但事实并非如此。

您可以添加

QOpenGLFunctions_4_3_Core
的数据成员,然后在获得OpenGL上下文时对其进行初始化,并通过该对象调用任何GL函数。然后您可以在删除上下文之前删除 GL 函数加载器。

© www.soinside.com 2019 - 2024. All rights reserved.