Подтвердить что ты не робот

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

У меня есть приложение wxWidgets, в котором есть несколько дочерних окон. Я использую свой собственный класс холста 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.
  • Двойная буферизация включена.
  • В Windows есть стили оформления WS_CLIPSIBLINGS и WS_CLIPCHILDREN.
  • В моем обработчике событий resize я сразу перерисовываю окно.

Я пробовал:

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

Отключение DWM не является опцией.

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

4b9b3361

Ответ 1

Это длинный снимок, но я просто решил точно эту же проблему сам.

Часть длинной части появляется, потому что мы делаем рисование владельца контура группы без надписей, которая окружает наше окно OpenGL (т.е. чтобы сделать красивую небольшую границу), и это может не описывать ваш случай.

То, что мы обнаружили, вызвало проблему:

Мы использовали вызов RoundRect() (с HOLLOW_BRUSH), чтобы нарисовать контур группы. Меняя его на вызовы MoveToEx() и LineTo(), чтобы убедиться, что строки просто нарисованы, и ничего не делается внутри группового окна, GDI не пытался перерисовать весь контент элемента управления. Возможно, существует разница в логике недействительности (или у нас была ошибка как-то при загрузке намеченной полой кисти). Мы по-прежнему расследуем.

-Noel

Ответ 2

Хм, может быть, вы столкнулись с одной и той же проблемой: если вы используете "новый" MFC он будет создавать и использовать приложения с вкладками и разделителем окон.

Сплиттер имеет некоторую логику (я угадываю где-то вокруг прозрачного окна и рисую XOR линии для раскола), что вызывает такое поведение. Удалите сплиттер, чтобы подтвердить его. ваш вопрос. Если вам нужна раздельная функциональность - поставьте другой разделитель.

Также вкладки разрешают стыковку и снова разделяют окна с той же проблемой - remove/replace.

Удачи, Игорь