当可见区域发生变化时,OpenGL插件会崩溃Chrome

时间:2012-02-18 12:52:32

标签: google-chrome opengl npapi firebreath

我正在使用Windows上的FireBreath(现在)开发一个插件,其中包括使用OpenGL显示网络摄像头源。我正在使用一个带窗口的插件,而且我是从一个单独的线程中绘制的。代码可以在这里查看:

标头文件

https://github.com/EvilTengil/kinect-at-home-plugin/blob/0007beecf136ff2e5e1aa50be94d4906447a8f43/Win/KinectAtHomeWin.h

源文件

https://github.com/EvilTengil/kinect-at-home-plugin/blob/0007beecf136ff2e5e1aa50be94d4906447a8f43/Win/KinectAtHomeWin.cpp

(忽略onWindowResized中的奇怪代码,这只是提交中保留的一些测试。)

问题在于,只要重新调整浏览器窗口的大小以便更改插件的可见区域或者扩展名以某种方式滚动到滚动框的可见区域之外,插件就会在Chrome中崩溃。我没有安装Firefox,但我猜它是一个NpApi的东西,因为它在Internet Explorer中工作。

我相信正在发生的事情是Chrome会在插件的可见尺寸发生变化时发布并创建新的HDC。这可能导致渲染上下文无效,但它仍然在插件中使用并导致崩溃。

当发生这种情况时,我注意到NPP_SetWindow被调用了,但是在NpapiPluginModule_NPP.cpp中忽略了那些调用,所以我无法连接到这个事件。

我已经谷歌几个小时了,但没有找到任何帮助。有没有人有这方面的经验?

我有一个想法,如果我创建自己的子窗口到插件窗口,我可以处理我自己的DC,它可以工作。我做了一些失败的快速测试,这可能是因为我蹩脚的Win32技能。但这可以用更多的工作吗?我的另一个想法是以某种方式跟踪可见区域,但我还没有看到它。

1 个答案:

答案 0 :(得分:1)

Windows处理失效不应导致程序崩溃。但OpenGL,即它的扩展需要一些特殊的预防措施,特别是如果主机程序也使用OpenGL。

使用OpenGL的任何类型的插件或DLL都必须小心,即在使用它们之前将其所需的资源置于一个理智的状态,并在完成后将它们放回去。对于OpenGL来说,这意味着,每次开始使用它之前,您应该重新绑定您的上下文:

HDC hOldDC = wglGetCurrentDC();
HRC hOldContext = wglGetCurrentContext();

 // first unbind old context/DC from current thread
wglMakeCurrent(NULL, NULL);

 // then bind our context
wglMakeCurrent(hMyDC, hMyContext);

 // this is essential, as in Windows the addresses of extensions
 // may depend on the active context, so you must reinitialise
 // extension function pointers!
reinitialize_extensions();

/* NOW USE OPENGL FUNCTION

 // cleaning up once we're done:
wglMakeCurrent(NULL, NULL);
wglMakeCurrent(hOldDC, hOldRC);
// remember that we also need to reset extension
// function pointers to the other context
reinitialize_extensions();

由于在Window扩展函数中,指针依赖于上下文,因此将它们放入结构并通过该结构调用它们是有意义的。这节省了整个扩展重新初始化的事情。在C ++中,您可以将整个OpenGL上下文包装在一个类中。

请记住,每次通过NP-API调用插件时,都需要完成此设置/拆解。