errorman

不积跬步,无以至千里

导航

QOpenGLContext Class

Posted on 2023-03-15 16:19  Clemens  阅读(848)  评论(0编辑  收藏  举报

Detailed Description 详细描述

QOpenGLContext表示底层OpenGL上下文的OpenGL状态。为了设置上下文,需要设置其屏幕和格式,使它们与上下文所需使用的表面的屏幕和格式相匹配,必要时使用setShareContext()使其共享资源,最后调用create()。使用返回值或isValid()来检查是否成功初始化上下文。

可以通过调用makeCurrent()将上下文设置为当前surface的上下文。当完成OpenGL渲染时,调用swapBuffers()交换surface的前后缓冲区,以便新渲染的内容变得可见。为了支持某些平台,QOpenGLContext要求在调用swapBuffers()之后开始渲染新帧之前再次调用makeCurrent()。

如果暂时不需要上下文,例如当应用程序未呈现时,删除它以释放资源可能很有用。您可以连接到 aboutToBeDestroy() 信号来清理与 QOpenGLContext 本身分配的所有权不同的任何资源。

一旦QOpenGLContext被设置为当前上下文,可以使用Qt的OpenGL使能器(例如QOpenGLFunctions、QOpenGLBuffer、QOpenGLShaderProgram和QOpenGLFramebufferObject)以跨平台的方式进行渲染。也可以直接使用平台的OpenGL API,而不使用Qt使能器,但可能会牺牲可移植性。当想要使用OpenGL 1.x或OpenGL ES 1.x时,必须使用后者。

有关OpenGL API的更多信息,请参阅官方OpenGL文档。

有关如何使用QOpenGLContext的示例,请参见OpenGL Window示例。

 

Thread Affinity

可以使用moveToThread()将QOpenGLContext移动到不同的线程中。不要从与QOpenGLContext对象所属的线程不同的线程中调用makeCurrent()。一个上下文一次只能在一个线程中处于当前状态,并且只能针对一个surface,并且一个线程一次只能有一个当前上下文。

 

Context Resource Sharing

资源,例如纹理和顶点缓冲对象,可以在不同的上下文之间共享。在调用create()之前使用setShareContext()指定应该共享这些资源的上下文。QOpenGLContext内部跟踪一个QOpenGLContextGroup对象,可以通过shareGroup()访问它,并可用于查找给定共享组中的所有上下文。共享组包括已成功初始化并正在与共享组中的现有上下文共享的所有上下文。非共享上下文具有由单个上下文组成的共享组。

 

Default Framebuffer

在某些平台上,取决于当前surface,帧缓冲0之外的帧缓冲可能是默认帧缓冲。建议您使用glBindFramebuffer(ctx->defaultFramebufferObject())而不是调用glBindFramebuffer(0),以确保您的应用程序在不同平台之间具有可移植性。但是,如果您使用QOpenGLFunctions::glBindFramebuffer(),这将自动为您完成。

另请参见QOpenGLFunctions、QOpenGLBuffer、QOpenGLShaderProgram和QOpenGLFramebufferObject。

 

Member Type Documentation

enum QOpenGLContext::OpenGLModuleType
这个枚举定义了底层 OpenGL 实现的类型。
Constant Value Description
QOpenGLContext::LibGL 0 OpenGL
QOpenGLContext::LibGLES 1 OpenGL ES 2.0 or higher
这个枚举是在 Qt 5.3 中引入或修改的。

 

Member Function Documentation

QOpenGLContext::QOpenGLContext(QObject *parent = nullptr)

使用父对象 parent 创建一个新的 OpenGL 上下文实例。
在使用它之前,您需要设置正确的format并调用 create()。
另见 create() 和 makeCurrent()。

 

[signal] void QOpenGLContext::aboutToBeDestroyed()

这个信号在底层原生 OpenGL 上下文被销毁之前发出,这样用户就可以清理 OpenGL 资源,否则这些资源在共享 OpenGL 上下文的情况下可能会悬而未决。
如果您希望使上下文成为当前上下文以便进行清理,请确保仅使用直接连接来连接到信号。

 

[virtual] QOpenGLContext::~QOpenGLContext()

销毁 QOpenGLContext 对象。
如果这是线程的当前上下文,则还会调用 doneCurrent()。

 

[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 Core profile上下文,那么您将获得 3.2 Core profile上下文。

如果本机上下文已成功创建并准备好与 makeCurrent()、swapBuffers() 等一起使用,则返回 true。

注意:如果上下文已经存在,这个函数会先销毁现有的上下文,然后再创建一个新的上下文。

另见 makeCurrent() 和 format()。

 

[static] QOpenGLContext *QOpenGLContext::currentContext()

返回在当前线程中调用 makeCurrent 的最后一个上下文,如果没有当前上下文,则返回 nullptr。

 

GLuint QOpenGLContext::defaultFramebufferObject() const

调用它以获取当前surface的默认帧缓冲区对象。

在某些平台(例如 iOS)上,默认的帧缓冲区对象取决于渲染到的表面,并且可能不同于 0。因此,您应该调用 glBindFramebuffer(ctx->defaultFramebufferObject()) 而不是调用 glBindFramebuffer(0), 如果您希望您的应用程序跨不同的 Qt 平台工作。
如果您在 QOpenGLFunctions 中使用 glBindFramebuffer(),则不必担心这一点,因为它会在传递 0 时自动绑定当前上下文的 defaultFramebufferObject()。

注意:通过帧缓冲区对象呈现的Widgets,如 QOpenGLWidget 和 QQuickWidget,将在绘画处于活动状态时覆盖从该函数返回的值,因为此时正确的“默认”帧缓冲区是widget的关联后备帧缓冲区,而不是属于顶层窗口的表面特定于平台的帧缓冲区 。这确保了此函数和依赖它的其他类(例如,QOpenGLFramebufferObject::bindDefault() 或 QOpenGLFramebufferObject::release())的预期行为。

另见 QOpenGLFramebufferObject。

 

void QOpenGLContext::doneCurrent()

用于调用具有 0 surface 的 makeCurrent 的便利功能。

这会导致当前线程中没有上下文是最新的。

另请参阅 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(),则返回底层平台上下文的format。
否则,返回请求的format。
请求的format和实际format可能不同。 请求给定的 OpenGL 版本并不意味着生成的上下文将完全针对请求的版本。 只保证创建的上下文的版本/配置文件/选项组合与请求兼容,只要驱动程序能够提供这样的上下文。
例如,请求 OpenGL 版本 3.x core profile 上下文可能会导致 OpenGL 4.x core profile 上下文。 同样,对 OpenGL 2.1 的请求可能会导致启用已弃用功能的 OpenGL 3.0 上下文。 最后,根据驱动程序的不同,不受支持的版本可能会导致上下文创建失败或最高支持版本的上下文。
缓冲区大小也可能存在类似的差异,例如,生成的上下文可能具有比请求的更大的深度缓冲区。 这是完全正常的。
另见 setFormat()。

 

QOpenGLFunctions *QOpenGLContext::functions() const

获取此上下文的 QOpenGLFunctions 实例。
QOpenGLContext 提供了这个作为访问 QOpenGLFunctions 的便捷方式,而无需手动管理它。
上下文或共享上下文必须是最新的。
返回的 QOpenGLFunctions 实例已准备好使用,不需要调用 initializeOpenGLFunctions()。

 

QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName) const

解析指向 OpenGL 扩展函数的函数指针,由 procName 标识
如果找不到这样的函数,则返回 nullptr。

 

QFunctionPointer QOpenGLContext::getProcAddress(const char *procName) const

这是一个重载函数。
这个函数是在 Qt 5.8 中引入的。

 

[static] QOpenGLContext *QOpenGLContext::globalShareContext()

返回应用程序范围的共享 OpenGL 上下文(如果存在)。 否则,返回 nullptr。
如果您需要在创建或显示 QOpenGLWidget 或 QQuickWidget 之前上传 OpenGL 对象(缓冲区、纹理等),这将很有用。
注意:您必须在创建 QGuiApplication 对象之前在 QGuiApplication 上设置 Qt::AA_ShareOpenGLContexts 标志,否则 Qt 可能无法创建全局共享上下文。
警告:不要试图使此函数返回的上下文在任何表面上成为当前上下文。 相反,您可以创建一个与全局上下文共享的新上下文,然后使新上下文成为当前上下文。
这个函数是在 Qt 5.5 中引入的。
另见 Qt::AA_ShareOpenGLContexts、setShareContext() 和 makeCurrent()。

 

bool QOpenGLContext::hasExtension(const QByteArray &extension) const

如果此 OpenGL 上下文支持指定的 OpenGL extension,则返回 true,否则返回 false。
上下文或共享上下文必须是最新的。
另见 extensions()。

 

bool QOpenGLContext::isOpenGLES() const

如果上下文是 OpenGL ES 上下文,则返回 true。
如果尚未创建上下文,则结果基于通过 setFormat() 设置的请求格式。
这个函数是在 Qt 5.3 中引入的。
另见 create()、format() 和 setFormat()。

 

bool QOpenGLContext::isValid() const

返回此上下文是否有效,即已成功创建的。

在某些平台上,先前成功创建的上下文的返回值 false 表示 OpenGL 上下文丢失。

在应用程序中处理上下文丢失情况的典型方法是在 makeCurrent() 失败并返回 false 时通过此函数进行检查。 如果此函数随后返回 false,则通过调用 create() 重新创建底层原生 OpenGL 上下文,再次调用 makeCurrent(),然后重新初始化所有 OpenGL 资源。
另见 create()。

 

bool QOpenGLContext::makeCurrent(QSurface *surface)

将当前线程的上下文与给定的surface关联起来。如果成功,返回true;否则返回false。如果表面未暴露或由于应用程序被挂起等原因导致图形硬件不可用,则可能会发生后者。

如果surface为0,则等效于调用doneCurrent()。

避免从与QOpenGLContext实例所在线程不同的线程调用此函数。如果希望从不同的线程中使用QOpenGLContext,应先确保它在当前线程中没有被关联,如果必要,可以调用doneCurrent()。然后在使用它之前,调用moveToThread(otherThread)将其移到其他线程中。

默认情况下,Qt采用一种检查,强制执行线程亲和性的上述条件。仍然可以通过设置Qt::AA_DontCheckOpenGLContextThreadAffinity应用程序属性来禁用此检查。请确保理解在其他线程中使用QObjects的后果,如QObject线程亲和性文档中所述。

另请参见functions(),doneCurrent()和Qt::AA_DontCheckOpenGLContextThreadAffinity。

 

QVariant QOpenGLContext::nativeHandle() const

返回上下文的本机句柄(native handle)。

此函数提供对QOpenGLContext底层本机上下文的访问。返回的variant包含一个特定于平台的值类型。这些类可以在QtPlatformHeaders模块中找到。

在不支持检索本机句柄的平台上,或者如果既没有调用create()也没有调用setNativeHandle(),则返回一个空的variant。

该函数在Qt 5.4中引入。 另请参见setNativeHandle()。

 

[static] void *QOpenGLContext::openGLModuleHandle()

返回当前正在使用的OpenGL实现的特定于平台的句柄(例如,Windows上的HMODULE)。

在不使用动态GL切换的平台上,返回值为nullptr。 该库可能仅支持GL,这意味着窗口系统接口函数(例如EGL)可能存在于另一个单独的库中。

注意:此函数要求QGuiApplication实例已经被创建。

该函数在Qt 5.3中引入。 另请参见openGLModuleType()。

 

[static] QOpenGLContext::OpenGLModuleType QOpenGLContext::openGLModuleType()

返回底层的OpenGL实现类型。

在不动态加载OpenGL实现的平台上,返回值在编译时确定,永远不会改变。

注意:桌面OpenGL实现也可能能够创建兼容ES的上下文。因此,在大多数情况下,更合适的是检查QSurfaceFormat::renderableType()或使用方便函数isOpenGLES()。

注意:此函数要求QGuiApplication实例已经被创建。

该函数在Qt 5.3中引入。

 

QScreen *QOpenGLContext::screen() const

返回上下文所创建的screen。

另请参见setScreen()。

 

void QOpenGLContext::setFormat(const QSurfaceFormat &format)

设置OpenGL上下文应兼容的format。在其生效之前,您需要调用create()。

当未通过此函数显式设置格式时,将使用QSurfaceFormat::defaultFormat()返回的格式。这意味着,在具有多个上下文的情况下,对该函数的单独调用可以由在创建第一个上下文之前调用QSurfaceFormat::setDefaultFormat()的单个调用替换。

另请参见format()。

 

void QOpenGLContext::setNativeHandle(const QVariant &handle)

设置此上下文的本机句柄(native handles)。当调用create()并设置本机句柄时,配置设置(例如format())将被忽略,因为此QOpenGLContext将包装已经创建的本机上下文,而不是从头开始创建一个新的上下文。

在某些平台上,本机上下文句柄不足够,并且必须提供其他相关句柄(例如,对于窗口或显示器)。因此,句柄是包含平台特定值类型的variant。这些类可以在QtPlatformHeaders模块中找到。

当使用设置了本机句柄的create()时,QOpenGLContext不会拥有这些句柄,因此销毁QOpenGLContext不会销毁本机上下文。

注意:一些框架在内部跟踪当前上下文和表面。通过Qt使采用的QOpenGLContext成为当前上下文对这些其他框架的内部状态没有影响。因此,通过其他框架进行的后续makeCurrent可能没有效果。因此,建议在通过Qt执行OpenGL操作后进行显式调用以使没有上下文和表面成为当前,以重置其他框架的内部状态。

注意:在使用其他框架创建的窗口和表面中使用Qt窗口和Qt上下文,或在Qt窗口和上下文中使用其他框架创建的窗口和表面,可能会因上下文和窗口像素格式的潜在不匹配而导致意外结果,具体取决于平台。为确保不会发生这种情况,请避免同时将不同框架的上下文和表面设置为当前。相反,建议使用基于上下文共享的方法,其中OpenGL资源(如纹理)可以从Qt和外部框架的上下文中访问。

此函数引入于Qt 5.4。 另请参见nativeHandle()。

 

void QOpenGLContext::setScreen(QScreen *screen)

设置OpenGL上下文应该适用于的screen。您需要在调用create()函数之前调用此函数才能生效。

另请参见screen()函数。

 

void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)

这个上下文需要调用create()方法后才能与shareContext共享纹理、着色器和其他OpenGL资源。

请参阅shareContext()方法。

 

QOpenGLContext *QOpenGLContext::shareContext() const

返回此上下文创建时使用的共享上下文。如果底层平台无法支持请求的共享,则将返回0。

请参阅setShareContext()方法。

 

QOpenGLContextGroup *QOpenGLContext::shareGroup() const

返回此上下文所属的共享组。

 

[static] bool QOpenGLContext::supportsThreadedOpenGL()

如果平台支持在主(GUI)线程之外进行OpenGL渲染,则返回true。该值由使用的平台插件控制,也可能取决于图形驱动程序。

此函数在Qt 5.5中引入。

 

QSurface *QOpenGLContext::surface() const

返回与此上下文关联的表面。这是传递给makeCurrent()方法的表面。

 

void QOpenGLContext::swapBuffers(QSurface *surface)

交换surface的后备缓冲区和前置缓冲区。 在OpenGL渲染完成一帧后调用此方法,并确保在发出任何其他OpenGL命令之前再次调用makeCurrent()方法,例如作为新帧的一部分。

 

QAbstractOpenGLFunctions *QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile = QOpenGLVersionProfile()) const

返回指向一个对象的指针,该对象提供对此上下文的versionProfile的所有函数的访问。只要此上下文是当前上下文,就不需要调用QAbstractOpenGLFunctions::initializeOpenGLFunctions()方法。也可以在上下文不是当前上下文时调用此函数,但在这种情况下,调用者有责任通过调用QAbstractOpenGLFunctions::initializeOpenGLFunctions()方法来确保适当的初始化。

通常,我们会使用此函数的模板版本,以自动将结果转换为正确的类型。

 

TYPE *QOpenGLContext::versionFunctions() const

此函数重载了versionFunctions()方法。

返回指向一个对象的指针,该对象提供对此上下文的版本和配置文件的所有函数的访问。只要此上下文是当前上下文,就不需要调用QAbstractOpenGLFunctions::initializeOpenGLFunctions()方法。也可以在上下文不是当前上下文时调用此函数,但在这种情况下,调用者有责任通过调用QAbstractOpenGLFunctions::initializeOpenGLFunctions()方法来确保适当的初始化。

通常,我们会使用此函数的模板版本,以自动将结果转换为正确的类型。

  QOpenGLFunctions_3_3_Core* funcs = 0;
  funcs = context->versionFunctions<QOpenGLFunctions_3_3_Core>();
  if (!funcs) {
      qWarning() << "Could not obtain required OpenGL context version";
      exit(1);
  }

可以请求一个不同于上下文创建时的版本和配置文件的函数对象。要做到这一点,可以使用指定所需函数对象类型的模板版本的此函数,或者将一个QOpenGLVersionProfile对象作为参数传递给非模板函数。 请注意,请求其他版本或配置文件的函数对象可能会失败,并且在这样做时会返回nullptr。无法满足请求的情况包括请求不在此上下文版本或配置文件中的函数。例如:

  • 请求3.3核心配置文件函数对象将成功。
  • 请求3.3兼容性配置文件函数对象将失败。由于这些函数已经被弃用,我们无法解析它们。
  • 请求4.3核心配置文件函数对象将失败。由于4.0-4.3版本中引入了新的核心函数,我们无法解析它们。
  • 请求3.1函数对象将成功。3.1中没有任何不在3.3核心中的内容。

请注意,如果通过此方法创建一个函数对象,则QOpenGLContext将保留该对象的所有权。这是为了允许对象被缓存和共享。