Hace tiempo que la comunidad nos está reportando errores con la extensión 3D y algunas tarjetas gráficas: fundamentalmente con las ATI y las INTEL. Esto ocurre en sistemas operativos linux cuando se está utilizando el driver libre, también conocido como driver Mesa, y que viene por defecto. El error es grave, puesto que al intentar arrancar una vista 3d todo gvSIG se cierra sin dejar rastro[1].
Descripción del problema
Para entender bien el problema se debe valorar el efecto que tiene usar un determinado driver sobre el rendimiento gráfico del sistema. Si los drivers no están instalados correctamente o si no son los adecuados la carga recae sobre el procesador. Así una tarjeta de última generación apenas podría mover aplicaciones 3D complejas.
En sistemas operativos Windows esto no suele dar mayor problema, puesto que la instalación de drivers es una labor sencilla, y normalmente, los aporta el fabricante.
En linux la cosa cambia, hay drivers libres y drivers privados. Y según la tarjeta gráfica que tengas podrás utilizar unos u otros. Históricamente las tarjetas NVIDIA han tenido mejor soporte con su driver privado, aunque ahora esto está cambiando. Para aumentar la confusión, las tarjetas ATI disponen de drivers libres (llamados Mesa) y drivers privados (conocidos como fglrx). Los mismos drivers Mesa sirven también para una amplia gama de tarjetas, entre los que se incluyen las Intel. En Ubuntu si tienes una ATI o una Intel se activa por defecto el driver Mesa.
El modo de aportar aceleración gráfica en linux es mediante la adición del módulo DRI(direct rendering) y GLX en la carga de las X. Estos módulos suelen enlazar con una librería llamada libGL y que aporta la implementación de la API de OpenGL que es necesaria para obtener aceleración gráfica. De modo que cada driver aporta su implementación de OpenGL que está optimizado para un determinado tipo de tarjetas.
En gvSIG3D se hace un uso extenso de OpenGL desde el grafo de escena en el que se basa. Por lo que el driver utilizado es de suma importancia.
Por otro lado está el tema del manejo de memoria y la carga de librerías. En linux cada proceso tiene su espacio de memoria reservado, y a la vez comparte un espacio global con el resto del sistema. La carga de librerías dinámicas por parte de un proceso se realiza mediante la llamada dlopen (dynamic library open).
Por defecto cada proceso realiza la carga de librerías en su espacio de memoria. De esta manera un proceso no tendrá acceso al espacio de memoria de otro. Tampoco tendrá acceso a los símbolos que cargan sus librerías a no ser que estas librerías se carguen en el espacio global de memoria del sistema.
Retomando el hilo inicial (gvSIG3D hace crash! con mi tarjeta ATI o Intel en Ubuntu), parece ser que el problema reside en que las librerías DRI y GLX del driver Mesa, ya no enlazan con libGL directamente.
Por tanto esta librería ya no se encuentra cargada en el espacio global de memoria. En consecuencia el driver no es capaz de encontrar los símbolos de OpenGL requeridos a no ser que se carguen en el espacio global de memoria.
En C++ es posible arreglar este problema mediante el uso del flag RTDL_GLOBAL en la llamada dlopen() haciendo algo parecido a esto antes de levantar un contexto de render[2]:
/* Make sure libGL symbols will be visible to the driver */
glhandle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL);
/**para más info mirar en [3]**/
Sin embargo la problemática asociada con gvSIG3D va más allá. En nuestro caso es jogl (JavaOpenGL) el que levanta el contexto de render. Java carga la librería jogl mediante la llamada System.loadLibrary() e internamente lanza este dlopen() . Sin embargo la llamada no se realiza con el flag RTLD_GLOBAL (que haría visible al driver los símbolos requeridos). Como esta llamada la realiza Java internamente, nos impide poder definir los flags.
Soluciones
En este momento estamos decidiendo que solución adoptar, puesto que arreglar el fallo con mediación del usuario es bastante sencillo. Se trata de precargar la librería antes de ejecutar el programa, de este modo los símbolos estarán disponibles.
En caso de tener Ubuntu en una consola ejecutar :
1. glxinfo | grep rendering
Si en la consola aparece "direct rendering: Yes " puedes seguir el proceso . Si no, no tienes aceleración 3D, estás usando el procesador en lugar de la tarjeta gráfica. El rendimiento será muy bajo.
2. glxinfo | grep renderer
Si aparece algo como "OpenGL renderer string : Mesa DRI ..." estás utilizando los drivers mesa. Enhorabuena :D, quizá el fallo pueda solucionarse, aunque es posible que el rendimiento no sea muy alto.
3. export LD_PRELOAD=/usr/lib/libGL.so.1
y después en la misma consola (muy importante) ejecutar la aplicación gvSIG (mediante el script gvSIG.sh.) en la que tengas instalada la extensión 3D.
4. ./ruta-a-gvSIG_1.9/bin/gvSIG.sh
gvSIG debe de estar iniciándose....
5. Intenta abrir una vista 3D.
Sin embargo hacerlo de manera automática y para todos los usuarios (todas las tarjetas/drivers) ya no es tan sencillo. Entre las opciones que estamos discutiendo se encuentran las siguientes:
1. Levantar nosotros mismos el contexto de render, y así al mismo tiempo eliminamos la dependencia que tenemos con jogl.
2. Intentar averiguar mediante script que tipo de driver/tarjeta tiene el usuario y ejecutar el LD_PRELOAD en función de que implementación de libGL se esté usando.
3. Añadir este problema a la lista de problemas conocidos y dejar la solución en forma de parche, para aquel que se la quiera descargar.
Esperamos aportar la solución definitiva en el siguiente build (bn14). Para los que necesiten una solución inmediata pueden utilizar el procedimiento que se indica arriba.
Si el procedimiento no te ha funcionado, contacta con nosotros en las listas de gvSIG o en este mismo blog. Suerte!
[1]http://forge.osor.eu/tracker/?func=detail&group_id=89&aid=13153&atid=732
[2]http://www.xfree86.org/current/DRI11.html
[3]http://www.mail-archive.com/mesa3d-dev@lists.sourceforge.net/msg01152.html
Hace 2 días