背景
用QT学校OpenGL绝对可以事半功倍,QT提供了一系列对OpenGL的支持,包括OPenGL窗口类,对OpenGL函数的面向对象的封装等。
总体说明
在Qt框架中,makeCurrent
是QOpenGLContext
类的一个方法,它封装了这些平台特定的调用,提供了一个跨平台的接口来管理OpenGL上下文。makeCurrent
函数的作用是将一个特定的OpenGL上下文(context)设置为当前线程的渲染上下文。这意味着,当你调用OpenGL函数进行绘制时,这些函数将操作这个指定的上下文。每个OpenGL上下文包含了一整套OpenGL的状态信息,比如纹理绑定、帧缓冲对象(FBO)的配置等。
当你创建一个OpenGL窗口或帧缓冲对象时,通常会与一个上下文对象关联。在进行绘制之前,你需要通过makeCurrent
函数来激活这个上下文,这样OpenGL的命令就会作用于这个上下文。在Qt中,如果你继承了QOpenGLWidget
并重写了initializeGL
、resizeGL
或paintGL
函数,那么在这些函数中你不需要手动调用makeCurrent
,因为这些函数被调用时,Qt会自动将你的QOpenGLWidget
的上下文设置为当前上下文。
在某些情况下,如果你需要在这些虚函数之外的地方进行OpenGL绘制,那么你需要手动调用makeCurrent
来激活上下文。例如,在QOpenGLWidget
的构造函数或析构函数中,如果你需要创建或销毁OpenGL资源,你应该首先调用makeCurrent
,然后进行资源的创建或销毁,最后调用doneCurrent
来释放当前的上下文。
在多线程环境中,每个线程可以有自己的当前上下文,但是一个上下文在同一时间只能被一个线程设置为当前。如果你尝试在不同的线程中使用同一个上下文,可能会导致不可预测的行为或程序崩溃。
总结来说,makeCurrent
函数是OpenGL编程中用于管理上下文状态的关键函数,它确保了OpenGL命令能够正确地应用于你想要操作的特定上下文。
makeCurrent 如何实上下文现切换?
这个上下文应该指的就是线程中,声明的一些变量。QT的 QOpenGLWidget
并重写了initializeGL
、resizeGL
或paintGL
函数,本身就是在当前的创建的OpenGL线程里面, 所以,不存在切换。
但是,如果你在其他地方调用OpenGL的函数。就是在其他线程里面,
上下文就不一样(不是同一个线程)。你需要将QOpenGLWidget的上下文通过moveToThread转移到该线程,并手动调用makeCurrent()和doneCurrent()来管理上下文的当前状态。
我觉得理解到这里,就可以了,就不会觉得调用这个函数奇怪了。
当然你还想继续探究,可以看看下面这段总结:
makeCurrent
函数的实现细节依赖于操作系统和OpenGL的实现,但通常它涉及到以下几个步骤:
-
激活上下文 :
makeCurrent
函数首先会激活(或"使当前")一个特定的OpenGL上下文。这通常涉及到与操作系统的API调用,以确保所有后续的OpenGL命令都指向这个上下文。 -
线程局部存储 :OpenGL上下文通常与一个线程关联。
makeCurrent
可能会使用线程局部存储(Thread Local Storage, TLS)来存储当前线程的OpenGL上下文指针。这样,当OpenGL命令被调用时,它们可以查找TLS来找到当前激活的上下文。 -
资源绑定:在上下文被激活后,所有与之前上下文相关的资源绑定(如纹理、缓冲区、帧缓冲等)都会被解绑,以便新的上下文可以绑定它自己的资源。
-
状态切换:操作系统或OpenGL的实现会负责更新内部状态,以确保OpenGL的状态机反映了新上下文的状态。这可能包括切换GPU的渲染目标、更新GPU的管线状态等。
-
错误处理 :如果尝试激活的上下文无效或与当前线程不兼容,
makeCurrent
函数会返回错误。在某些实现中,这可能涉及到检查上下文是否已经与另一个线程绑定,或者是否与当前的设备上下文(如Windows中的HDC)不匹配。
在不同的平台上,makeCurrent
函数的具体实现可能会有所不同:
-
Windows :在Windows平台上,
makeCurrent
可能会调用Win32 APIwglMakeCurrent
,它接受一个设备上下文(HDC)和一个渲染上下文(HGLRC)作为参数。 -
macOS :在macOS上,
makeCurrent
可能会使用NSOpenGL API,如[NSOpenGLContext makeCurrentContext:]
。 -
Linux/X11 :在Linux上,可能会使用GLX API,如
glXMakeCurrent
。 -
EGL :对于使用EGL的嵌入式系统或某些现代OpenGL ES实现,
makeCurrent
可能会调用eglMakeCurrent
,它接受显示(EGLDisplay)、绘制表面(EGLSurface)和上下文(EGLContext)作为参数。
在Qt框架中,makeCurrent
是QOpenGLContext
类的一个方法,它封装了这些平台特定的调用,提供了一个跨平台的接口来管理OpenGL上下文。当你调用makeCurrent
时,Qt会负责处理所有底层的切换逻辑。