QOpenGLContext Class
QOpenGLContext 类表示一个本机 OpenGL 上下文,支持在QSurface 上进行 OpenGL 渲染。更多内容...
| 头文件: | #include <QOpenGLContext> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Gui) target_link_libraries(mytarget PRIVATE Qt6::Gui) |
| qmake: | QT += gui |
| 继承自: | QObject |
- 所有成员列表(包括继承的成员)
- QOpenGLContext 属于“3D 渲染”部分。
公共类型
| enum | OpenGLModuleType { LibGL, LibGLES } |
公共函数
| QOpenGLContext(QObject *parent = nullptr) | |
| virtual | ~QOpenGLContext() |
| bool | create() |
| GLuint | defaultFramebufferObject() const |
| void | doneCurrent() |
| QSet<QByteArray> | extensions() const |
| QOpenGLExtraFunctions * | extraFunctions() const |
| QSurfaceFormat | format() const |
| QOpenGLFunctions * | functions() const |
| QFunctionPointer | getProcAddress(const QByteArray &procName) const |
| QFunctionPointer | getProcAddress(const char *procName) const |
| bool | hasExtension(const QByteArray &extension) const |
| bool | isOpenGLES() const |
| bool | isValid() const |
| bool | makeCurrent(QSurface *surface) |
| QNativeInterface * | nativeInterface() const |
| QScreen * | screen() const |
| void | setFormat(const QSurfaceFormat &format) |
| void | setScreen(QScreen *screen) |
| void | setShareContext(QOpenGLContext *shareContext) |
| QOpenGLContext * | shareContext() const |
| QOpenGLContextGroup * | shareGroup() const |
| QSurface * | surface() const |
| void | swapBuffers(QSurface *surface) |
信号
| void | aboutToBeDestroyed() |
静态公共成员
| bool | areSharing(QOpenGLContext *first, QOpenGLContext *second) |
| QOpenGLContext * | currentContext() |
| QOpenGLContext * | globalShareContext() |
| QOpenGLContext::OpenGLModuleType | openGLModuleType() |
| bool | supportsThreadedOpenGL() |
详细描述
QOpenGLContext 表示底层 OpenGL 上下文的 OpenGL 状态。 要设置上下文,请将其屏幕和格式设置为与该上下文计划使用的一个或多个表面相匹配;如有必要,可使用 `setShareContext()` 使其与其他上下文共享资源;最后调用 `create()`。使用返回值或 `isValid()` 来检查上下文是否已成功初始化。
可以通过调用makeCurrent() 将上下文设为某个给定表面的当前上下文。当 OpenGL 渲染完成后,请调用swapBuffers() 来交换该表面的前缓冲区和后缓冲区,以便新渲染的内容变得可见。 为了支持某些平台,QOpenGLContext 要求您在调用swapBuffers() 之后,于开始渲染新帧之前再次调用makeCurrent()。
如果暂时不需要该上下文(例如应用程序未进行渲染时),删除它以释放资源会很有帮助。您可以订阅aboutToBeDestroyed() 信号,以清理所有与 QOpenGLContext 本身拥有权不同的已分配资源。
一旦将 QOpenGLContext 设为当前上下文,即可通过使用 Qt 的 OpenGL 启用器(如QOpenGLFunctions 、QOpenGLBuffer 、QOpenGLShaderProgram 和QOpenGLFramebufferObject )以平台无关的方式进行渲染。虽然可能以牺牲可移植性为代价,但也可以直接使用平台的 OpenGL API,而无需使用 Qt 启用器。 若需使用 OpenGL 1.x 或 OpenGL ES 1.x,则必须采用后者。
有关 OpenGL API 的更多信息,请参阅官方OpenGL 文档。
有关如何使用 QOpenGLContext 的示例,请参阅OpenGL 窗口示例。
线程亲和性
可以使用 `moveToThread()` 将 `QOpenGLContext` 移动到另一个线程。请勿在与 `QOpenGLContext` 对象所属线程不同的线程中调用 `makeCurrent()`。一个上下文一次只能在一个线程中、针对一个表面作为当前上下文,而一个线程一次也只能有一个当前上下文。
上下文资源共享
纹理和顶点缓冲对象等资源可在上下文之间共享。在调用create() 之前,请先调用setShareContext() 以指定上下文应共享这些资源。QOpenGLContext 内部会跟踪一个QOpenGLContextGroup 对象,可通过shareGroup() 访问该对象,并利用它查找给定共享组中的所有上下文。 一个共享组由所有已成功初始化且与该共享组中现有上下文共享资源的上下文组成。一个非共享上下文的共享组仅包含一个上下文。
默认帧缓冲区
在某些平台上,根据当前绘制面的不同,默认帧缓冲区可能不是 0。建议使用 glBindFramebuffer(ctx->defaultFramebufferObject()) 代替 glBindFramebuffer(0),以确保应用程序在不同平台间具有可移植性。 不过,如果您使用QOpenGLFunctions::glBindFramebuffer(),系统会自动为您完成此操作。
警告:WebAssembly
我们建议在QSurface 的整个生命周期内,仅通过QSurface 将一个 QOpenGLContext 设为当前上下文。如果使用多个上下文,请务必注意:在 WebAssembly 平台上,多个 QOpenGLContext 实例可能由底层同一个本机上下文支持。 因此,在两个 QOpenGLContext 对象上使用相同的QSurface 调用makeCurrent() 时,第二次调用可能不会切换到不同的原生上下文。结果,在第二次makeCurrent() 之后进行的任何 OpenGL 状态更改,都可能同时改变第一个 QOpenGLContext 的状态,因为它们都由同一个原生上下文支持。
注意:这意味着 当将现有的基于 Qt OpenGL 的代码移植到 WebAssembly 时,可能需要进行一些改动以应对这些限制。
安全性注意事项
QOpenGLContext 及其派生类(例如QOpenGLFunctions 、QtOpenGL 模块类以及带有 OpenGL 后端的QRhi )所使用的所有数据,均被视为可信内容。这包括着色器源代码、顶点和索引数据、纹理及其他像素数据,以及传递给 OpenGL 函数的所有参数。 Qt 不会对其中任何内容进行验证或净化处理。
另请注意,getProcAddress() 返回的是由 OpenGL 实现根据名称解析出的原始函数指针。Qt 无法验证调用者对其进行强制转换后的签名是否与实现提供的签名匹配;若此处出错,将导致未定义行为。
Qt OpenGL 实现(即驱动程序,以及在具备相应库的平台上的分派库)是一个可信的、进程内的平台依赖项。Qt 会直接加载并调用它,不进行任何沙箱隔离或验证,其处理方式与对待 Vulkan 实现相同。
加载哪个库由平台的常规共享库搜索顺序决定,在某些平台上还取决于环境变量。该选择是部署可信配置的一部分:无法控制此配置的部署,就无法控制进程内部运行的原生代码。
警告: 建议应用程序开发 人员在允许引入不属于应用程序且不受开发者控制的用户提供内容之前,仔细考虑其潜在影响。
另请参阅 QOpenGLFunctions 、QOpenGLBuffer 、QOpenGLShaderProgram 以及QOpenGLFramebufferObject 。
成员类型文档
enum QOpenGLContext::OpenGLModuleType
此枚举定义了底层 OpenGL 实现的类型。
| 常量 | 值 | 描述 |
|---|---|---|
QOpenGLContext::LibGL | 0 | OpenGL |
QOpenGLContext::LibGLES | 1 | OpenGL ES 2.0 或更高版本 |
成员函数文档
[explicit] QOpenGLContext::QOpenGLContext(QObject *parent = nullptr)
创建一个以父对象 `parent` 为父的新 OpenGL 上下文实例。
在能够使用它之前,您需要设置正确的格式并调用create()。
另请参阅 create() 和makeCurrent()。
[virtual noexcept] QOpenGLContext::~QOpenGLContext()
销毁QOpenGLContext 对象。
如果这是线程的当前上下文,则还会调用 `doneCurrent()`。
[signal] void QOpenGLContext::aboutToBeDestroyed()
该信号在底层原生 OpenGL 上下文被销毁之前发出,以便用户能够清理 OpenGL 资源——否则在共享 OpenGL 上下文的情况下,这些资源可能会处于悬空状态。
如果您希望将该上下文设为当前上下文以进行清理,请确保仅通过直接连接来订阅该信号。
注意:在 Qt for Python中 ,当该信号由QOpenGLWidget 或QOpenGLWindow 的析构函数发出时,由于Python实例已被销毁,因此不会接收到该信号。我们建议改在QWidget::hideEvent()中进行清理。
[static] bool QOpenGLContext::areSharing(QOpenGLContext *first, QOpenGLContext *second)
如果first 和second 上下文共享OpenGL资源,则返回true 。
bool QOpenGLContext::create()
尝试使用当前配置创建 OpenGL 上下文。
当前配置包括格式、共享上下文和屏幕。
如果系统上的 OpenGL 实现不支持所请求的 OpenGL 上下文版本,则QOpenGLContext 将尝试创建最接近的匹配版本。 可以使用format() 函数返回的QSurfaceFormat 来查询实际创建的上下文属性。例如,如果您请求一个支持 OpenGL 4.3 核心配置文件的上下文,但驱动程序和/或硬件仅支持 3.2 核心配置文件上下文,那么您将获得一个 3.2 核心配置文件上下文。
如果原生上下文已成功创建且可与makeCurrent()、swapBuffers() 等函数配合使用,则返回true 。
注意:如果 上下文已存在,此函数会先销毁现有上下文,然后创建一个新的上下文。
另请参阅 makeCurrent() 和format()。
[static] QOpenGLContext *QOpenGLContext::currentContext()
返回当前线程中最后一次调用makeCurrent 的上下文;如果没有当前上下文,则返回nullptr 。
GLuint QOpenGLContext::defaultFramebufferObject() const
调用此函数可获取当前渲染面的默认帧缓冲区对象。
在某些平台(例如 iOS)上,默认帧缓冲区对象取决于要渲染到的绘制表面,因此可能不为 0。 因此,如果您希望应用程序在不同的 Qt 平台上都能正常运行,则不应调用 glBindFramebuffer(0),而应调用 glBindFramebuffer(ctx->defaultFramebufferObject())。
如果您在QOpenGLFunctions 中使用glBindFramebuffer(),则无需担心此问题,因为当传入0时,它会自动绑定当前上下文的defaultFramebufferObject()。
注意: 通过帧缓冲区对象进行渲染的小部件 (如QOpenGLWidget 和QQuickWidget )在绘制活动期间会覆盖此函数返回的值,因为此时正确的“默认”帧缓冲区是该小部件关联的后备帧缓冲区,而不是属于顶级窗口表面的平台特定帧缓冲区。 这确保了本函数及其依赖它的其他类(例如QOpenGLFramebufferObject::bindDefault() 或QOpenGLFramebufferObject::release())能表现出预期的行为。
另请参阅 QOpenGLFramebufferObject 。
void QOpenGLContext::doneCurrent()
用于调用makeCurrent 并传入0表面值的便捷函数。
这将导致当前线程中不存在任何有效上下文。
另请参阅 makeCurrent() 和currentContext()。
QSet<QByteArray> QOpenGLContext::extensions() const
返回该上下文所支持的 OpenGL 扩展集。
当前上下文或共享上下文必须处于活动状态。
另请参阅 hasExtension()。
QOpenGLExtraFunctions *QOpenGLContext::extraFunctions() const
获取此上下文对应的QOpenGLExtraFunctions 实例。
QOpenGLContext 提供此方法,以便于访问QOpenGLExtraFunctions ,而无需手动管理它。
上下文或共享上下文必须为当前上下文。
返回的QOpenGLExtraFunctions 实例已准备就绪,无需调用 initializeOpenGLFunctions()。
注意: QOpenGLExtraFunctions 包含一些功能,无法保证在运行时可用。运行时的可用性取决于平台、图形驱动程序以及应用程序请求的 OpenGL 版本。
另请参阅 QOpenGLFunctions 和QOpenGLExtraFunctions 。
QSurfaceFormat QOpenGLContext::format() const
如果已调用create(),则返回底层平台上下文的格式。
否则,返回请求的格式。
请求的格式与实际格式可能存在差异。请求特定的 OpenGL 版本并不意味着生成的上下文会完全针对该请求的版本。仅保证所创建上下文的版本/配置文件/选项组合与请求兼容,前提是驱动程序能够提供此类上下文。
例如,请求 OpenGL 3.x 核心配置文件上下文可能会得到一个 OpenGL 4.x 核心配置文件上下文。同样,请求 OpenGL 2.1 可能会得到一个启用了已弃用函数的 OpenGL 3.0 上下文。 最后,根据驱动程序的不同,不支持的版本可能会导致上下文创建失败,或者生成最高支持版本的上下文。
缓冲区大小方面也可能存在类似的差异,例如,生成的上下文的深度缓冲区可能比请求的更大。这是完全正常的。
另请参阅 setFormat()。
QOpenGLFunctions *QOpenGLContext::functions() const
获取此上下文对应的QOpenGLFunctions 实例。
QOpenGLContext 提供此方法作为访问 `QOpenGLFunctions ` 的便捷方式,无需手动管理它。
上下文或共享上下文必须为当前上下文。
返回的QOpenGLFunctions 实例已准备就绪,无需调用 initializeOpenGLFunctions()。
QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName) const
解析由procName 标识的OpenGL扩展函数的函数指针。
使用此函数可访问 OpenGL 扩展函数或核心函数,这些函数在某些平台上可能无法作为链接符号提供。
返回的指针可能因平台而异。某些系统即使该函数无效或不受支持,也可能返回一个非nullptr 的指针。
要可靠地检查函数的可用性,请通过调用QOpenGLContext::hasExtension() 来测试扩展的支持情况。对于核心函数,请通过QOpenGLContext::format() 返回的QSurfaceFormat 中的version() 检查当前上下文的版本。
QFunctionPointer QOpenGLContext::getProcAddress(const char *procName) const
这是一个重载函数。
[static] QOpenGLContext *QOpenGLContext::globalShareContext()
如果存在,则返回全局共享的 OpenGL 上下文;否则,返回 `nullptr`。
如果您需要在创建或显示QOpenGLWidget 或QQuickWidget 之前上传OpenGL对象(缓冲区、纹理等),此函数将非常有用。
警告:请 勿尝试将此函数返回的上下文设为任何表面的当前上下文。相反,您可以创建一个与全局上下文共享的新上下文,然后将新上下文设为当前上下文。
另请参阅 Qt::AA_ShareOpenGLContexts 、setShareContext() 和makeCurrent()。
bool QOpenGLContext::hasExtension(const QByteArray &extension) const
如果该 OpenGL 上下文支持指定的 OpenGLextension ,则返回true ;否则返回false 。
上下文或共享上下文必须为当前上下文。
另请参阅 extensions()。
bool QOpenGLContext::isOpenGLES() const
如果上下文是 OpenGL ES 上下文,则返回 true。
如果上下文尚未创建,则结果基于通过setFormat() 设置的请求格式。
另请参阅 create()、format() 和setFormat()。
bool QOpenGLContext::isValid() const
如果该上下文有效(即已成功创建),则返回真。
在某些平台上,对于先前已成功创建的上下文,false 的返回值会表明该 OpenGL 上下文已丢失。
应用程序中处理上下文丢失情况的典型方法是,每当makeCurrent() 失败并返回false 时,通过此函数进行检查。如果该函数返回false ,则通过调用create() 重新创建底层本机 OpenGL 上下文,再次调用makeCurrent(),然后重新初始化所有 OpenGL 资源。
在某些平台上,上下文丢失的情况无法避免。但在其他平台上,可能需要主动启用该功能。这可以通过在QSurfaceFormat 中启用ResetNotification 来实现。这将导致在底层原生OpenGL上下文中将RESET_NOTIFICATION_STRATEGY_EXT 设置为LOSE_CONTEXT_ON_RESET_EXT 。随后,QOpenGLContext 将在每次调用makeCurrent()时通过glGetGraphicsResetStatusEXT() 监控状态。
另请参阅 create()。
bool QOpenGLContext::makeCurrent(QSurface *surface)
将上下文设为当前线程中的活动上下文,并基于给定的surface 。成功时返回true ;否则返回false 。后者可能发生在表面未暴露,或者由于应用程序被挂起等原因导致图形硬件不可用时。
如果surface 为nullptr ,则这等同于调用doneCurrent()。
请避免从与QOpenGLContext 实例所在线程不同的线程调用此函数。若需在其他线程中使用QOpenGLContext ,应先通过调用doneCurrent()(如有必要)确保该对象在当前线程中并非活动状态,然后在其他线程中使用前调用 moveToThread(otherThread)。
默认情况下,Qt 会进行一项检查,以确保线程亲和性符合上述条件。您仍可通过设置Qt::AA_DontCheckOpenGLContextThreadAffinity 应用程序属性来禁用此检查。请务必了解在所属线程之外使用 QObject 可能带来的后果,具体说明请参见QObject thread affinity 文档。
另请参阅 functions()、doneCurrent() 以及Qt::AA_DontCheckOpenGLContextThreadAffinity 。
template <typename QNativeInterface> QNativeInterface *QOpenGLContext::nativeInterface() const
返回该上下文中指定类型的本机接口。
该函数提供了对 `QOpenGLContext` 的平台特定功能的访问,这些功能在 `QNativeInterface ` 命名空间中定义:
macOS 上 NSOpenGLContext 的原生接口 | |
EGL 上下文的原生接口 | |
GLX 上下文的原生接口 | |
Windows 上的 WGL 上下文的原生接口 |
如果请求的接口不可用,则返回一个 `nullptr ` 对象。
[static] QOpenGLContext::OpenGLModuleType QOpenGLContext::openGLModuleType()
返回底层的 OpenGL 实现类型。
在 OpenGL 实现未被动态加载的平台上,返回值在编译时确定且永远不会改变。
注意:桌面版 OpenGL实现可能也 具备创建 ES 兼容上下文的能力。因此,在大多数情况下,检查 `QSurfaceFormat::renderableType()` 或使用便捷函数 `isOpenGLES()` 更为合适。
注意:此 函数要求已创建QGuiApplication 实例。
QScreen *QOpenGLContext::screen() const
返回该上下文所创建的屏幕。
另请参阅 setScreen()。
void QOpenGLContext::setFormat(const QSurfaceFormat &format)
设置 OpenGL 上下文应兼容的format 。需先调用create() 才能生效。
如果未通过此函数显式设置格式,则将使用QSurfaceFormat::defaultFormat()返回的格式。这意味着,当存在多个上下文时,可以在创建第一个上下文之前,通过一次调用QSurfaceFormat::setDefaultFormat()来替代对本函数的多次单独调用。
另请参阅 format()。
void QOpenGLContext::setScreen(QScreen *screen)
设置OpenGL上下文应适用的screen 。需先调用create(),该设置才会生效。
另请参阅 screen()。
void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)
使该上下文与shareContext 共享纹理、着色器及其他OpenGL资源。您需要先调用create(),该设置才会生效。
另请参阅 shareContext()。
QOpenGLContext *QOpenGLContext::shareContext() const
返回创建此上下文时所使用的共享上下文。
如果底层平台无法支持所请求的共享操作,则返回 0。
另请参阅 setShareContext()。
QOpenGLContextGroup *QOpenGLContext::shareGroup() const
返回该上下文所属的共享组。
[static] bool QOpenGLContext::supportsThreadedOpenGL()
如果平台支持在主(GUI)线程之外进行 OpenGL 渲染,则返回true 。
该值由所使用的平台插件控制,也可能取决于图形驱动程序。
QSurface *QOpenGLContext::surface() const
返回当前上下文所关联的曲面。
这是作为参数传递给makeCurrent() 的表面。
void QOpenGLContext::swapBuffers(QSurface *surface)
交换surface 的后缓冲区和前缓冲区。
调用此函数以完成一帧 OpenGL 渲染,并在发出任何后续 OpenGL 命令之前(例如作为新帧的一部分),务必再次调用makeCurrent()。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.