c++ windows opengl direct3d dwm

c++ - OpenGL parpadea/dañado con el tamaño de la ventana y el DWM activo



windows direct3d (2)

Esta es una apuesta arriesgada, pero acabo de resolver exactamente este mismo problema yo mismo.

La parte de disparo largo entra porque hacemos un dibujo del esquema de un cuadro de grupo sin texto que rodea nuestra ventana OpenGL (es decir, para hacer un pequeño borde), y eso puede no describir su caso.

Lo que encontramos causó que el problema fuera este:

Hemos estado utilizando una llamada RoundRect () (con HOLLOW_BRUSH) para dibujar el contorno del cuadro de grupo. Cambiando a un MoveToEx () y LineTo () llama para asegurarse de que las líneas se dibujan y no se hace nada dentro del cuadro de grupo mantuvo el GDI de tratar de repintar inesperadamente todo el contenido del control. Es posible que exista una diferencia en la lógica de invalidación (o tenemos un error de alguna manera al cargar el pincel hueco deseado). Aún estamos investigando.

-Navidad

Tengo una aplicación wxWidgets que tiene varias ventanas abiertas para niños. Estoy usando mi propia clase de canvas GL, no la de wx. Las ventanas comparten su contexto OpenGL. No creo que el hecho de que sea wxwidgets sea realmente relevante aquí.

Las ventanas abiertas son hijos de una ventana que son hermanos entre sí, contenidos dentro de un control de tabulación. Tipo de interfaz de estilo MDI, pero no es una ventana MDI. Cada una puede cambiarse de tamaño individualmente. Todo funciona de maravilla a menos que Aero esté habilitado y el DWM esté activo.

Cambiar el tamaño de cualquier ventana (ni siquiera las ventanas abiertas) hace que todas las ventanas abiertas parpadeen ocasionalmente con una vista de almacén obsoleto que contiene cualquier basura que haya estado en la pantalla en ese punto que no esté abierta. Esto SOLO sucede con Aero habilitado.

Estoy bastante seguro de que este es el DWM que no tiene el contenido abierto en su tienda de respaldo y que la ventana no está repintada en el momento correcto.

He intentado muchas cosas para evitar esto, tengo una solución pero no es muy buena e implica leer el framebuffer con glReadPixels en un DIB y luego ajustarlo a la pintura DC en mi rutina onPaint. Esta solución solo está habilitada si DWM está activo, pero prefiero no tener que hacer esto en absoluto, ya que perjudica el rendimiento un poco (pero no está mal en un sistema capaz: las escenas son gráficos 3D relativamente simples). Tampoco se recomienda mezclar GDI y OpenGL pero este enfoque funciona, sorprendentemente. Puedo vivir con esto por ahora, pero preferiría no tener que hacerlo. Todavía tengo que hacer esto en WM_PRINT si quiero tomar una captura de pantalla de la ventana secundaria de todos modos, no veo una forma de evitar eso.

¿Alguien sabe de una mejor solución para esto?

Antes de que nadie me pregunte, definitivamente hago lo siguiente:

  • La clase de ventana tiene CS_OWNDC
  • WM_ERASEBACKGROUND no hace nada y devuelve TRUE.
  • Double Buffering está habilitado.
  • Windows tiene los estilos de ventana WS_CLIPSIBLINGS y WS_CLIPCHILDREN.
  • En mi controlador de eventos de cambio de tamaño, vuelvo a pintar la ventana.

He intentado:

  • Estableciendo PFD_SUPPORT_COMPOSITION en el descriptor de formato de píxel.
  • No utiliza un wxPaintDC en el controlador de pintura y llama a :: ValidateRect (hwnd, NULL) en su lugar.
  • Manejando WM_NCPAINT y excluyendo el área del cliente
  • Desactivar la pintura NC a través de la API DWM
  • Excluyendo el área del cliente en el evento de pintura
  • Llamando glFlush y / o glFinish antes y después del intercambio de buffer.
  • Invalidar la ventana en cada evento de pintura (¡como prueba!) - ¡todavía parpadea!
  • No se usa un contexto GL compartido.
  • Inhabilitando el doble buffering
  • Escribiendo a GL_FRONT_AND_BACK

Desactivar DWM no es una opción.

Y hasta donde sé, esto es incluso un problema si está utilizando Direct3D en lugar de OpenGL , aunque no lo he probado, ya que representa mucho trabajo.


Hmm, tal vez te hayas topado con el mismo problema: si estás utilizando un "nuevo" MFC, creará una aplicación con pestañas y Window Spliter.

El divisor tiene cierta lógica (supongo que en algún lugar alrededor de la ventana transparente y dibujar líneas XOR para la división) que causa este comportamiento. Retire el divisor para confirmar que resuelva su problema. Si necesita funcionalidad dividida, coloque un divisor diferente.

Además, las pestañas permiten el acoplamiento y, una vez más, la división de las ventanas que tiene el mismo problema: eliminar / reemplazar.

Buena suerte, Igor