多线程opengl 创建位图失败之解决方案
2010年07月08日
[b]多线程opengl 创建位图失败之解决方案[/b]
最近一直在做opengl多线程,遇到的问题是:在多线程中使用opengl的glGenTextures来画位图时无效果,在网上搜索了三天,问了好多网友和技术群,都无一例外的没有得到答案。
终于昨天在网上搜索时找到了相关的信息,解决方案如下,如你也遇到这个问题,希望我能提供给你帮助。
[b]转载自:[/b][b]http://zhidao.baidu.com/question/77393242.html[/b]
你在你的分线程里调用
wglMakeCurrent来把HDC和当前可用的HGLRC连接起来,记住,OPENGL的HGLRC同一时间只能在一个线程内使用,也就是说它是线程安全的,当然你这个线程结束前必须调用wglMakeCurrent (NULL, NULL)
如果在你的版本中这样做也不成功的话
建议你在进入线程的时候用
wglCreateContext (hdc);
wglMakeCurrent (hdc, hglrc);
线程退出前用
wglMakeCurrent (NULL, NULL) ;
wglDeleteContext (hglrc);
这样一般都没问题
=================================================
如果你是动态在你的线程里面创建这个控件的话就没问题
如果你是用消息线程创建的话就不行了,你无法在你自己创建的线程里使用
=================================================
原因我上面说了,OPENGL是线程安全的,它的渲染上下文是无法在多个线程里同时使用的;另:要开发OPENGL程序,如果你用MFC框架的话建议你先了解一下MFC;如果是纯SDK开发的话就需要着重研究OPENGL对运行环境的需求。可能你的VS版本高,有提供TIMER控件,这个是定时器来的,每间隔一段你定义好的时间它发送出一个WM_TIMER消息到你的窗口;如果你还不清楚TIMER的话建议你先去了解一下WINDOWS的消息机制;记住,OPENGL不是给初学编程的玩的;没有一定的基础,就算你写出了代码,你也不知道它为什么都是这样工作的;而且多线程编程是一个难点,不但要解决同步问题,调试起来也非常困难,经常会遇到些莫名其妙的问题。就像你这个问题一样,这问题是由于你对OPENGL运行要求不清楚导致的。
[b]转载自:[/b][b]http://blog.sina.com.cn/s/blog_4bb59dc40100fa57.html[/b]
wglMakeCurrent:
函数设定OpenGL当前线程(线程相关性)的渲染环境。以后这个线程所有的OpenGL调用都是在这个hdc标识的设备上绘制。你也可以使用wglMakeCurrent 函数来改变调用线程的当前渲染环境,使之不再是当前的渲染环境。
注意:
hdc参数的绘制表面必须是支持OpenGL的。它不需是wglCreateContext 创建hglrc时所传进来的hdc,但它必须是相同的设备并具有相同的像素格式。GDI转换的hdc将不被渲染环境所支持。当前的渲染环境将一直使用hdc设备环境直到它不再是当前渲染环境。
在切换到新的渲染环境之前,OpenGL将冲刷掉当前调用线程之前的所有渲染环境。
一个线程可以有一个渲染环境。所以一个多线程进程可以有多个渲染环境。一个线程在调用任何OpenGL函数之前必须设置一个当前渲染环境。否则所有OpenGL调用都将忽略。
在某一时刻渲染环境只能属于一个线程,你不能使一个渲染环境同时属于多个线程。
一个应用程序可以通过不同线程中的不同的当前渲染环境产生多个绘图,它支持各个线程都拥有自己的渲染环境的设备环境。
如果有错误发生,wglMakeCurrent 函数在返回之前将使渲染环境不作为线程当前的渲染环境。
[b]转载自:[/b][b]http://topic.csdn.net/u/20080408/17/54b76b63-1c46-4340-80ef-2b5bc4859f0c.html[/b]
找到了!
原来是因为OpenGL Context同时只能被一个线程拥有,而在创建OpenGL窗口时被主线程占据了。解决方法是用函数wglMakeCurrent( HDC hdc,HGLRC hglrc),该函数可以将OpenGL Context关联到调用此函数的线程:在主线程里加上一句wglMakeCurrent(NULL,NULL),解除关联,在子线程开始时用wglMakeCurrent(hdc,hglrc)使子线程取得Context就行了。
我是在一篇关于多线程的OpenGL的英文资料里看到的,原文主要是解决同时用两个线程操作OpenGL:一个渲染,一个创建显示列表。他用的方法是在渲染时渲染线程取得Context,结束后释放,另一个线程再占用……这样循环。
我估计甚至可以用wglMakeCurrent进行切换,实现多个线程同时往一个窗口上作图!当然不是完全同时,只是轮流占用而已。不过这样效率并不高,除了用于防止用户界面线程因作图运算量太大而被阻塞,应该没什么用处。
-----------------------------------------------
终于取到了glGenTextures(1, (UINT*)&m_nTexID)函数中的m_nTexID的值了,真不容易啊...
原来就是在子线程中取hDC和hRC,然后子线程运行完再返还hDC和hRC,不知道我这样说你理解不理解,不理解可以给我留言。呵呵
2010年07月08日
[b]多线程opengl 创建位图失败之解决方案[/b]
最近一直在做opengl多线程,遇到的问题是:在多线程中使用opengl的glGenTextures来画位图时无效果,在网上搜索了三天,问了好多网友和技术群,都无一例外的没有得到答案。
终于昨天在网上搜索时找到了相关的信息,解决方案如下,如你也遇到这个问题,希望我能提供给你帮助。
[b]转载自:[/b][b]http://zhidao.baidu.com/question/77393242.html[/b]
你在你的分线程里调用
wglMakeCurrent来把HDC和当前可用的HGLRC连接起来,记住,OPENGL的HGLRC同一时间只能在一个线程内使用,也就是说它是线程安全的,当然你这个线程结束前必须调用wglMakeCurrent (NULL, NULL)
如果在你的版本中这样做也不成功的话
建议你在进入线程的时候用
wglCreateContext (hdc);
wglMakeCurrent (hdc, hglrc);
线程退出前用
wglMakeCurrent (NULL, NULL) ;
wglDeleteContext (hglrc);
这样一般都没问题
=================================================
如果你是动态在你的线程里面创建这个控件的话就没问题
如果你是用消息线程创建的话就不行了,你无法在你自己创建的线程里使用
=================================================
原因我上面说了,OPENGL是线程安全的,它的渲染上下文是无法在多个线程里同时使用的;另:要开发OPENGL程序,如果你用MFC框架的话建议你先了解一下MFC;如果是纯SDK开发的话就需要着重研究OPENGL对运行环境的需求。可能你的VS版本高,有提供TIMER控件,这个是定时器来的,每间隔一段你定义好的时间它发送出一个WM_TIMER消息到你的窗口;如果你还不清楚TIMER的话建议你先去了解一下WINDOWS的消息机制;记住,OPENGL不是给初学编程的玩的;没有一定的基础,就算你写出了代码,你也不知道它为什么都是这样工作的;而且多线程编程是一个难点,不但要解决同步问题,调试起来也非常困难,经常会遇到些莫名其妙的问题。就像你这个问题一样,这问题是由于你对OPENGL运行要求不清楚导致的。
[b]转载自:[/b][b]http://blog.sina.com.cn/s/blog_4bb59dc40100fa57.html[/b]
wglMakeCurrent:
函数设定OpenGL当前线程(线程相关性)的渲染环境。以后这个线程所有的OpenGL调用都是在这个hdc标识的设备上绘制。你也可以使用wglMakeCurrent 函数来改变调用线程的当前渲染环境,使之不再是当前的渲染环境。
注意:
hdc参数的绘制表面必须是支持OpenGL的。它不需是wglCreateContext 创建hglrc时所传进来的hdc,但它必须是相同的设备并具有相同的像素格式。GDI转换的hdc将不被渲染环境所支持。当前的渲染环境将一直使用hdc设备环境直到它不再是当前渲染环境。
在切换到新的渲染环境之前,OpenGL将冲刷掉当前调用线程之前的所有渲染环境。
一个线程可以有一个渲染环境。所以一个多线程进程可以有多个渲染环境。一个线程在调用任何OpenGL函数之前必须设置一个当前渲染环境。否则所有OpenGL调用都将忽略。
在某一时刻渲染环境只能属于一个线程,你不能使一个渲染环境同时属于多个线程。
一个应用程序可以通过不同线程中的不同的当前渲染环境产生多个绘图,它支持各个线程都拥有自己的渲染环境的设备环境。
如果有错误发生,wglMakeCurrent 函数在返回之前将使渲染环境不作为线程当前的渲染环境。
[b]转载自:[/b][b]http://topic.csdn.net/u/20080408/17/54b76b63-1c46-4340-80ef-2b5bc4859f0c.html[/b]
找到了!
原来是因为OpenGL Context同时只能被一个线程拥有,而在创建OpenGL窗口时被主线程占据了。解决方法是用函数wglMakeCurrent( HDC hdc,HGLRC hglrc),该函数可以将OpenGL Context关联到调用此函数的线程:在主线程里加上一句wglMakeCurrent(NULL,NULL),解除关联,在子线程开始时用wglMakeCurrent(hdc,hglrc)使子线程取得Context就行了。
我是在一篇关于多线程的OpenGL的英文资料里看到的,原文主要是解决同时用两个线程操作OpenGL:一个渲染,一个创建显示列表。他用的方法是在渲染时渲染线程取得Context,结束后释放,另一个线程再占用……这样循环。
我估计甚至可以用wglMakeCurrent进行切换,实现多个线程同时往一个窗口上作图!当然不是完全同时,只是轮流占用而已。不过这样效率并不高,除了用于防止用户界面线程因作图运算量太大而被阻塞,应该没什么用处。
-----------------------------------------------
终于取到了glGenTextures(1, (UINT*)&m_nTexID)函数中的m_nTexID的值了,真不容易啊...
原来就是在子线程中取hDC和hRC,然后子线程运行完再返还hDC和hRC,不知道我这样说你理解不理解,不理解可以给我留言。呵呵