Приложение Qt MDI с OpenGL:как сделать действительный скриншот?
-
20-09-2019 - |
Вопрос
у меня есть МДИ приложение, написанное на Qt.Некоторые из подокн включают в себя QGLWidget
s, то есть контексты OpenGL.Наиболее заметные из них используют вершинные и фрагментные шейдеры OpenGL для визуализации данных.
Мне нужно программно сделать снимок экрана главного окна приложения, включая, конечно, все подокна, которые оказываются видимыми.На первый взгляд это звучит просто («определенно спрашивали много раз, так что давайте просто погуглим!»), но после более внимательного рассмотрения кажется, что это становится немного сложнее...
Теперь вот что я пробовал:
QPixmap::grabWidget
не работает для подокна, использующих шейдерные программы, по-видимому, потому, что контекст перенаправления, похоже, не поддерживает необходимые расширения OpenGL.(Код рендеринга проверяет, поддерживает ли связанный контекст необходимые расширения, и отказывается продолжать, если нет.)QPixmap::grabWindow
молча оставляет все контексты OpenGL пустыми — даже те, которые используют только базовые примитивы.QGLWidget::grabFrameBuffer
работает, но захватывает только контекст OpenGL конкретного подокна, тогда как я хотел бы захватить все приложение (по сути, то, чтоAlt+PrtScr
делает в Windows).
Я также попробовал сначала выполнить № 2, а затем выполнить итерацию № 3 для всех подокна, просто копируя результат № 3 в нужное место изображения из № 2.Это работало очень хорошо, пока я не сделал некоторые подокна перекрывающимися — в этом случае изображения из №3 перезаписывали рамки подокна и т. д.Таким образом, этот подход, вероятно, потребует гораздо больше кода для обработки всех неприятных угловых случаев...
Некоторая дополнительная информация:Как только я получу скриншот, я собираюсь объединить несколько из них в последовательность, чтобы создать видео — возможно, используя ffmpeg.Это делает этот вопрос своего рода продолжением (первой части) мой предыдущий вопрос;просто приложение превратилось из одноконтекстной автономной программы OpenGL в нечто, что использует Qt для общих окон и виджетов пользовательского интерфейса и встраивает графику в подокна.
Хотя я, конечно, предпочел бы хорошее кроссплатформенное решение в стиле Qt, я готов рассмотреть возможность использования и хака, специфичного для Windows.(Что должно быть возможно, как я вижу Alt+PrtScr
очень правильно поступаю.)
Итак, есть предложения?
Решение
Очень хакерски, но захватывает рабочий стол (не скрывая окно), как в этот урок и обрезать все, кроме окон?
В более общем плане я даже не уверен, что спецификация OpenGL требует, чтобы вывод помещался в передний буфер:реализация может просто использовать наложение видео (или махинации со сквозной передачей VGA в стиле Voodoo2) для вывода.
Другие советы
Единственное, что я могу придумать навскидку, это сделать следующий псевдокод:
for each window
grab the window into its own pixmap
grab the GL portions and paste into the windows
order the window pixmaps by depth of the window (deepest first)
initialize a common pixmap
for each window pixmap
paint the window pixmap into the common pixmap at the appropriate location.
Есть ли от этого польза??
Примеры Grabber показывают, как получить содержимое фреймбуфера OpenGL.