OpenGL мерцает/повреждается при изменении размера окна и активном DWM

У меня есть приложение wxWidgets, в котором есть несколько дочерних окон opengl. Я использую свой собственный класс холста GL, а не класс wx. Окна совместно используют свой контекст OpenGL. Я не думаю, что тот факт, что это wxwidgets, действительно имеет здесь значение.

Окна opengl являются дочерними элементами окон, являющихся одноуровневыми по отношению друг к другу и содержащимися в элементе управления вкладками. Вид интерфейса в стиле MDI, но это не окно MDI. Каждое из них может быть индивидуально изменено. Все прекрасно работает, если не включен Aero и не активен DWM.

Изменение размера любого окна (даже не opengl) приводит к тому, что все окна opengl время от времени мерцают с устаревшим представлением резервного хранилища, которое содержит любой мусор, который был на экране в тот момент, но не opengl. Это происходит ТОЛЬКО при включенном Aero.

Я почти уверен, что DWM на самом деле не имеет содержимого opengl в резервном хранилище поверхности для рисования и окно не перерисовывается в нужный момент.

Я перепробовал так много способов обойти это, у меня есть решение, но оно не очень приятное и включает в себя чтение фреймбуфера с помощью glReadPixels в DIB, а затем передачу его в DC рисования в моей подпрограмме onPaint.Этот обходной путь доступен только в том случае, если DWM активен, но я бы предпочел вообще не делать этого, поскольку это немного снижает производительность (но не так уж плохо в подходящей системе - сцены представляют собой относительно простые 3D-графики). Также не рекомендуется смешивать GDI и opengl, но этот подход работает, как ни странно. Я могу жить с этим на данный момент, но я бы не хотел. Мне все еще нужно сделать это в WM_PRINT, если я все равно хочу сделать снимок экрана дочернего окна, я не вижу способа обойти это.

Кто-нибудь знает лучшее решение этой проблемы?

Прежде чем кто-нибудь спросит, я определенно делаю следующее:

  • Класс Window имеет CS_OWNDC
  • WM_ERASEBACKGROUND ничего не делает и возвращает TRUE.
  • Включена двойная буферизация.
  • Окна имеют стили окон WS_CLIPSIBLINGS и WS_CLIPCHILDREN.
  • В своем обработчике события изменения размера я немедленно перекрашиваю окно.

Я пробовал:

  • Установка PFD_SUPPORT_COMPOSITION в дескрипторе формата пикселей.
  • Не использовать wxPaintDC в обработчике рисования и вызывать ::ValidateRect(hwnd, NULL) вместо этого.
  • Обработка WM_NCPAINT и исключение клиентской области
  • Отключение рисования ЧПУ через DWM API
  • Исключение клиентской области в событии рисования
  • Вызов glFlush и/или glFinish до и после замены буфера.
  • Инвалидация окна при каждом событии рисования (в качестве теста!) — по-прежнему мерцает!
  • Не используется общий контекст GL.
  • Отключение двойной буферизации.
  • Запись в GL_FRONT_AND_BACK

Отключение DWM невозможно.

И, насколько я знаю, это даже проблема, если вы используете Direct3D вместо OpenGL, хотя я не проверял это, так как это требует много работы.

25
задан Pete 17 May 2012 в 08:32
поделиться