2011-06-19 16 views
8

Estoy intentando crear una aplicación opengl multiproceso con libx11, con un hilo separado por ventana y un hilo administrador.Aplicación multiproceso X11 y OpenGL

que tienen un ciclo de eventos en el hilo gerente:

while(true) 
    while(XQLength(mPlatformData->display)){ 
    XNextEvent(mPlatformData->display, &event); 
    std::cout << "event" << std::endl; 
    } 
} 

Este es un gran bucle de eventos para aplicaciones de un solo subproceso, pero con esta configuración multiproceso suceden cosas extrañas.

Cuando estoy creando una ventana, necesito deshabilitar la cola de eventos, o GLXMakeCurrent simplemente se cuelga: mi hilo completo se detiene y no hace nada.

No encuentro mucha información sobre las aplicaciones multiproceso X11 en la red, ¿debo manejar mis eventos de forma diferente?

+0

Supongo que X11 y OpenGL son inseguros. –

+2

GL es seguro para subprocesos si uso un contexto/subproceso. Y de acuerdo con la documentación de X11, debería ser seguro si llamo a XInitThreads() primero, lo que hago. – Dutow

Respuesta

2

Se sabe que Xlib tiene varios problemas de tiempo de ejecución no corregibles que se manifiestan en situaciones de acceso concurent. Supongo que te estás encontrando exactamente con uno de esos.

Esta es una de las razones por las cuales se creó Xcb en primer lugar: Soluciona los problemas de Xlib. GLX se especifica contra Xlib, por lo que esto podría parecer como un tope de show cuando se trata de OpenGL. Sin embargo hay una envoltura Xlib alrededor Xcb y se puede utilizar con seguridad que la interfaz con GLX y seguir utilizando Xcb para el resto del programa: http://xcb.freedesktop.org/opengl/

veo dos soluciones posibles:

  1. poner un XLockDisplay/Mutex alrededor de XNextEvent y las llamadas GLX cada una; no es necesario bloquear para OpenGL ordinario, solo las funciones con el prefijo glX....

  2. Use Xcb para obtener un comportamiento correcto en el tiempo de ejecución y siga la guía que he vinculado anteriormente para que funcione con OpenGL/GLX.

+0

Implementé la primera solución como una solución rápida, pero espero que haya una mejor solución, probaré la segunda. – Dutow

1

¿Qué haces en tus hilos de renderizado? En cualquier caso, si comparte una conexión Display * entre diferentes hilos, debe llamar a XInitThreads.

He hecho buenas experiencias con una conexión de pantalla por hilo. Use XSelectInput para obtener eventos en su hilo principal. Los ID de ventana se pueden compartir en diferentes conexiones de Pantalla *.

+1

Hablando para el OP: El OP sabe acerca de XInitThreads, vea su comentario sobre su pregunta. Abrir una conexión adicional 'Display * 'es una forma de lidiar con esto. Desafortunadamente, consume un recurso raro: Conexiones. Los servidores X11 en su forma actual soportan de manera desafortunada solo un número bastante bajo de conexiones (clientes) a la vez (algo entre 256 y 1024); entonces, si cada uno de los hilos del proceso abriera una conexión de Pantalla propia, se quedaría sin ranuras de conexión muy rápidamente. – datenwolf

+1

Y las múltiples conexiones de pantalla no pueden haber compartido GLXContexts, o simplemente no pude hacer que funcionen. – Dutow

+0

@Dutow: puede compartir GLXContexts entre diferentes conexiones solo si los contextos involucrados son contextos de representación indirectos, es decir, llamada directa = falsa http://www.opengl.org/sdk/docs/man/xhtml/glXCreateContext.xml – datenwolf

2

Como dijo Eile, debería comprobar que usa XInitThreads.

Pude obtener algunos buenos resultados cuando usaba un hilo de fondo para hacer los dibujos de la ventana de una animación. Parece que no hay un problema real si te apegas al código de dibujo.

Si necesita más que eso y porque está utilizando libX11 de bajo nivel, lo mejor es simplemente abrir varias conexiones X11 y usar una conexión por ventana de nivel superior. Hice esto hace 10 años cuando jugué con el desarrollo de un kit de herramientas multiplataforma de BeOS y cuando todo estaba en peor estado, ahora lo es.

Puede usarlo incluso para el manejo de eventos y ventanas hijas de un nivel superior. Pero esto necesita un código muy complicado para las máscaras XEvent.

+0

Estoy usando XInitThreads, y no es suficiente. Y no puedo usar múltiples conexiones de pantalla, porque no puedo compartir GLXContext entre ellas. – Dutow

Cuestiones relacionadas