joethemow
joethemow

Reputation: 1773

QOpenGLWidget's context is null

I am trying to add a QOpenGLWidget to my QGraphicsScene, but the application crashes when I call initializeOpenGLFunctions(). I am pretty sure that the context of OpenGLView is null and that is why it is crashing (provides no logs) for two reasons:

  1. When I print it, it outputs 0x0
  2. When I try to enable QOpenGLDebugLogger it outputs that there is no current context.

I thought that QOpenGLWidget would have an OpenGLContext out of the box. Any idea why the context is not getting set? Am I missing something in my initialization?

QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setOption(QSurfaceFormat::DebugContext);
QSurfaceFormat::setDefaultFormat(format);


OpenGLView view = new OpenGLView();

header

class OpenGLView : public QOpenGLWidget, protected QOpenGLFunctions
{
}
#include "OpenGLView.h"

OpenGLView::OpenGLView(QWidget *parent) : QOpenGLWidget(parent) {
    initializeGL();
}


void OpenGLView::initializeGL() {
    initializeOpenGLFunctions(); // crashes
//    ...
}

void OpenGLView::paintGL() {
//    ...
}

void OpenGLView::resizeGL(int w, int h) {
//    ...
}

Upvotes: 1

Views: 1621

Answers (1)

Minh
Minh

Reputation: 1735

It is because you called initializeGL() in the constructor. By that time, the context has not been initialized. The context is first initialized when the widget is shown. Details taken from Qt's source code below:

void QOpenGLWidgetPrivate::initialize()
{
    Q_Q(QOpenGLWidget);
    if (initialized)
        return;
    
    ...

    QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
    ctx->setFormat(requestedFormat);
    if (shareContext) {
        ctx->setShareContext(shareContext);
        ctx->setScreen(shareContext->screen());
    }
    if (Q_UNLIKELY(!ctx->create())) {
        qWarning("QOpenGLWidget: Failed to create context");
        return;
    }

    ...

    context = ctx.take();
    initialized = true;
    q->initializeGL();
}

bool QOpenGLWidget::event(QEvent *e)
{
    Q_D(QOpenGLWidget);
    switch (e->type()) {

    ...

    case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
        if (d->initialized && window()->windowHandle()
                && d->context->shareContext() != QWidgetPrivate::get(window())->shareContext())
        {
            // Special case: did grabFramebuffer() for a hidden widget that then became visible.
            // Recreate all resources since the context now needs to share with the TLW's.
            if (!QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts))
                d->reset();
        }
        if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
            d->initialize();
            if (d->initialized)
                d->recreateFbo();
        }
        break;

    ...

    }
    return QWidget::event(e);
}

Upvotes: 2

Related Questions