Retrieving 64-bit OpenGL Information with Qt: QOpenGLExtraFunctions::glGetInteger64i_v()


What it is

  • It simplifies retrieving 64-bit integer (GLint64) information from OpenGL by handling context management and potential version compatibility issues.
  • It's a wrapper around the core OpenGL function glGetInteger64i_v().
  • QOpenGLExtraFunctions::glGetInteger64i_v() is a convenience function provided by the Qt framework's QOpenGLExtraFunctions class.

When to use it

  • It's necessary for querying certain OpenGL state variables that return 64-bit integer values.
  • You'll typically use this function when working with OpenGL ES 3.x or OpenGL 3.x and 4.x contexts in your Qt GUI application.

How it works

    • Before using glGetInteger64i_v(), you must create a QOpenGLExtraFunctions object and initialize it with a valid QOpenGLContext. This establishes the connection between your Qt application and the underlying OpenGL context.
  1. Function Call

    • Once initialized, you can call glGetInteger64i_v(target, index, data):
      • target: An OpenGL enum specifying the query target (e.g., GL_MAX_FRAGMENT_TEXTURE_SIZE).
      • index: An integer index within the target.
      • data: A pointer to a GLint64 variable where the retrieved data will be stored.
  2. Data Retrieval

    • The function retrieves the requested 64-bit integer value from the OpenGL state and stores it in the memory location pointed to by data.

Compatibility Considerations

  • Qt's QOpenGLExtraFunctions class checks for compatibility and only exposes the function if it's supported in the current OpenGL context or if the necessary extensions are available.
  • glGetInteger64i_v() is not part of the core OpenGL functionality in older versions.

Additional Notes

  • glGetInteger64i_v() is useful when dealing with larger data values or when explicitly required by an OpenGL extension you're using.
  • For basic OpenGL functionality, Qt provides functions like glGetIntegerv() that work with 32-bit integers.

In summary

  • It simplifies context management and ensures compatibility with different OpenGL versions.
  • QOpenGLExtraFunctions::glGetInteger64i_v() is a Qt-specific way to retrieve 64-bit integer information from OpenGL in a Qt GUI application.


#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>

class MyWindow : public QWindow {
    Q_OBJECT

public:
    MyWindow(QScreen *screen = nullptr);
    ~MyWindow() override;

protected:
    void initialize();
    void paintEvent(QPaintEvent *event) override;

private:
    QOpenGLContext *context;
    QOpenGLExtraFunctions *funcs;
    GLint64 maxVertexTextureUnits;
};

MyWindow::MyWindow(QScreen *screen) : QWindow(screen) {
    setSurfaceType(QWindow::OpenGLSurface);
}

MyWindow::~MyWindow() {
    delete context;
}

void MyWindow::initialize() {
    // Create an OpenGL context
    context = new QOpenGLContext(this);
    context->setFormat(QSurfaceFormat::defaultFormat());
    context->setProfile(QSurfaceFormat::CoreProfile);
    if (!context->create()) {
        qFatal("Failed to create OpenGL context!");
    }

    if (!context->isOpenGLES()) {
        qWarning("Application is not using OpenGL ES. Some features might not be available.");
    }

    // Make the context current
    context->makeCurrent(this);

    // Get function pointers for extended functionality
    funcs = new QOpenGLExtraFunctions(context);

    // Query for maximum vertex texture units
    funcs->glGetInteger64i_v(GL_MAX_VERTEX_TEXTURE_UNITS, 0, &maxVertexTextureUnits);
    qDebug() << "Maximum vertex texture units:" << maxVertexTextureUnits;
}

void MyWindow::paintEvent(QPaintEvent *event) {
    // Your custom rendering code using OpenGL here
    // (This example doesn't render anything for simplicity)

    context->swapBuffers(this);
}

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    MyWindow window;
    window.initialize();
    window.show();

    return app.exec();
}

#include "mywindow.moc"
  1. Include Necessary Headers
    Include headers for Qt GUI classes (QGuiApplication, QQmlApplicationEngine, QWindow), OpenGL context management (QOpenGLContext), core OpenGL functions (QOpenGLFunctions), and Qt's extended OpenGL functions (QOpenGLExtraFunctions).
  2. MyWindow Class
    Define a MyWindow class that inherits from QWindow.
    • It has member variables for the OpenGL context (context), extended function pointers (funcs), and a variable to store the retrieved value (maxVertexTextureUnits).
    • The constructor sets the surface type to QWindow::OpenGLSurface.
    • The destructor deletes the context object.
    • The initialize() function:
      • Creates a new QOpenGLContext with a core profile.
      • Makes the context current.
      • Creates a QOpenGLExtraFunctions object to access extended OpenGL functions.
      • Calls glGetInteger64i_v() to query the maximum number of vertex texture units and stores it in maxVertexTextureUnits.
      • Prints the retrieved value using qDebug().
    • The paintEvent() function is a placeholder for your actual rendering code using OpenGL functions.
  3. main Function
    • Creates a QGuiApplication instance.
    • Creates a MyWindow object, initializes it using initialize(), and shows it.
    • Runs the application event loop with app.exec().
  • Run the compiled application to see the maximum vertex texture units printed on the console.
  • Include the Qt GUI development libraries when compiling. You can usually find instructions on Qt's documentation for your specific platform and compiler.
  • Save the code as mywindow.cpp.


    • If you're certain your target OpenGL version supports glGetInteger64i_v(), you can call it directly using the QOpenGLFunctions class:
    GLint64 maxVertexTextureUnits;
    funcs->glGetInteger64i_v(GL_MAX_VERTEX_TEXTURE_UNITS, 0, &maxVertexTextureUnits);
    
    • This approach avoids the overhead of QOpenGLExtraFunctions, but make sure compatibility is ensured, especially for older OpenGL versions.
  1. Casting to 32-bit Integer (with caution)

    • In some cases, the information you need might also be available through a 32-bit integer query. If you're confident the value won't exceed the 32-bit range on your target hardware, you can use glGetIntegerv():
    GLint maxVertexTextureUnits32;
    funcs->glGetIntegerv(GL_MAX_VERTEX_TEXTURE_UNITS, &maxVertexTextureUnits32);
    // Cast to 64-bit if necessary, but be cautious of potential data loss
    GLint64 maxVertexTextureUnits = static_cast<GLint64>(maxVertexTextureUnits32);
    
    • Caution
      This approach can lead to data loss if the actual value exceeds the 32-bit integer limit. Use it only if you're certain the value you're querying is guaranteed to be within the 32-bit range.
  2. Checking for Extension Availability

    • If glGetInteger64i_v() is not part of the core functionality in your target OpenGL version, you might need to check for the presence of relevant extensions like GL_ARB_query_objects or GL_EXT_texture_filter_anisotropic.
    • Qt's QOpenGLContext provides methods like hasExtension() to check for extension support.
    • If the extension is available, you can use the corresponding extension functions to retrieve the information you need.

Choosing the Right Alternative

  • If you're dealing with potentially large values, using glGetInteger64i_v() or checking for extension availability is recommended to avoid data loss.
  • For wider compatibility, QOpenGLExtraFunctions::glGetInteger64i_v() provides a safer approach that handles version checks internally.
  • If compatibility with older versions is not a concern and you're sure glGetInteger64i_v() is supported, using it directly might be slightly more efficient.
  • The best alternative depends on your specific context and OpenGL version requirements.