Плагин OpenGL аварийно завершает работу Chrome при изменении видимой области - PullRequest
2 голосов
/ 18 февраля 2012

Я разрабатываю плагин, использующий FireBreath для Windows (на данный момент), который, помимо прочего, отображает канал веб-камеры с использованием 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, поэтому я не могу подключиться к этому событию.

У меня Google уже несколько часов, но я не могу найти никакой помощи. У кого-нибудь есть опыт этого?

У меня есть идея, что это могло бы работать, если бы я создал свое собственное дочернее окно для окна плагина, где я мог бы обрабатывать свой собственный DC. Я провел небольшое быстрое тестирование, которое не удалось, вероятно, из-за моих слабых навыков Win32. Но может ли это работать с еще большей работой? У меня есть еще одна идея - как-то отследить видимую область, но я еще не рассматривал это.

1 Ответ

1 голос
/ 18 февраля 2012

Неправильные дескрипторы Windows не должны приводить к аварийному завершению работы программы. Но OpenGL, а именно его расширения, требуют особых мер предосторожности, особенно если хост-программа также использует OpenGL.

Любой плагин или DLL, которые используют OpenGL, должны позаботиться о том, чтобы их необходимые ресурсы были переведены в разумное состояние перед их использованием, а затем возвращены обратно. Для 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();

Поскольку в функциях расширения окна указатели зависят от контекста, имеет смысл поместить их в структуру и вызвать их через нее. Это сохраняет всю вещь повторной инициализации расширения. В C ++ вы можете обернуть весь контекст OpenGL в класс для этого.

Помните, что вам нужно проходить через эту настройку / демонтаж каждый раз, когда ваш плагин вызывается через NP-API.

...