Screen tearing en el navegador

Un ejemplo típico (simulado) de tearing en una imagen.

Ejemplo de los errores gráficos característicos del screen tearing: la imagen parece cortada y desplazada por varios sitios.

Como podéis apreciar en la imagen, el screen tearing puede ser bastante molesto. Afortunadamente, no es demasiado común. Todo suele ir genial… hasta que te toca sufrirlo a ti, claro. Y mi hora llegó hace un par de días.

Mi caso

Mi equipo corre con Antergos (distribución Linux basada en Arch Linux), tengo una tarjeta gráfica modesta (NVIDIA GeForce 9500 GT, con el driver libre nouveau), uso awesome como gestor de ventanas [1] y compton como gestor de composición [2] .

Pues anteayer, jugando con las transiciones CSS, una de ellas me provocaba un screen tearing terrible en Firefox y Chrome.

Antes de ponerme a buscar una solución, creé un jsbin y consulté con algunos compas linuxeros (gracias @AinusSolheim , @Beelzenef y @FreakViking ), para cerciorarme de que no era cosa de la transición o un error puntual de los navegadores (improbable). Descartadas esas posibilidades, me pasé media tarde revisando configuraciones, buscando en la red, cribando foros, probando soluciones

Solución

NOTA: Evidentemente, esta es la solución a mi caso concreto. Puede o no funcionar en configuraciones parecidas y es compartida únicamente con la esperanza de que a alguien le pueda servir de utilidad.

Después de un rato de búsqueda y pruebas infructuosas, llegué a la conclusión de que tenía que ver con el Vsync, una opción del pintado de pantalla que se usa para evitar el screen tearing.

Revisando las opciones de compton desde consola, resulta que tiene varias opciones referentes tanto al Vsync como al tearing:

$ compton -h
compton (v0.1_beta2)
usage: compton [options]
Options:
...
--vsync vsync-method
  Set VSync method. There are up to 4 VSync methods currently available.
    none = No VSync
    drm = VSync with DRM_IOCTL_WAIT_VBLANK. May only work on some
      drivers.
    opengl = Try to VSync with SGI_video_sync OpenGL extension. Only
      work on some drivers.
    opengl-oml = Try to VSync with OML_sync_control OpenGL extension.
      Only work on some drivers. Experimental.
    opengl-swc = Try to VSync with SGI_swap_control OpenGL extension.
      Only work on some drivers. Works only with GLX backend.
      Does not actually control paint timing, only buffer swap is
      affected, so it doesn't have the effect of --sw-opti unlike
      other methods.
    opengl-mswc = Try to VSync with MESA_swap_control OpenGL
      extension. Basically the same as opengl-swc above, except the
      extension we use.
--vsync-aggressive
  Attempt to send painting request before VBlank and do XFlush()
  during VBlank. This switch may be lifted out at any moment.
...
--dbe
  Enable DBE painting mode, intended to use with VSync to
  (hopefully) eliminate tearing.

Pero aún aplicando las que parecían más lógicas, no conseguía resultados del todo satisfactorios. Vino a iluminarme definitivamente una entrada en los foros de Crunchbang (una distro basada en Debian muy recomendable, dicho sea de paso).

Solución usando sólo compton

En dicha publicación recomiendan crear un archivo de configuración simple para compton en ~/.config/compton.conf :

shadow = true;
no-dnd-shadow = true;
shadow-radius = 10;
shadow-offset-x = -16;
shadow-offset-y = -16;
shadow-opacity = 0.6;

y ejecutar compton con esta línea:

compton --opengl --vsync opengl-swc --paint-on-overlay -b

Esto lo puedes hacer directamente desde consola, para probar que tal funciona. Y, si te da buenos resultados, como a mí, añadirlo a donde quiera que establezcas los programas a ejecutarse con el arranque del sistema (yo lo hago en ~/.xinitrc , porque inicio sesión a pelo, con startx ).

Lo gracioso del asunto es que la opción --opengl que véis ahí no aparece en la ayuda mostrada en consola y cualquiera la adivina por ciencia infusa ¬_¬

De esta manera, corregimos el tearing usando sólo compton. Pero, siempre que se pueda (y funcione), es aconsejable hacerlo a través del driver de la gráfica.

Solución compton + nouveau

Para el driver libre (nouveau), que es el que yo uso, basta con añadir (o crearlo, si no existe) el siguiente contenido a la sección Device del archivo /etc/X11/xorg.conf.d/20-nouveau.conf :

Section "Device"
    Identifier "nvidia card"
    Driver "nouveau"
    Option "GLXVBlank" "true"
EndSection

Esto, en conjunción con la siguiente línea para compton, funcionó para mí (hay que reiniciar):

compton --opengl --paint-on-overlay -b &

Como veis, prescindo de la opción --vsync opengl-swc y, de paso, añado -b , para que compton se ejecute como un demonio.

Solución compton + nvidia

Cuando usamos el driver propietario, nvidia, podemos establecer esta opción gráficamente con la GUI de configuración nvidia-settings , marcando la opción sync to vblank. Y hasta ahí puedo llegar, porque no uso el driver propietario.

Nota adicional sobre Chrome

Con Chrome no basta con todo esto. Además hay que acceder desde el navegador a la página de funciones experimentales, chrome://flags/ y habilitar la primera opción: Ignorar la lista de renderización por software.

Página de funciones experimentales de Chrome.

Tras reiniciar Chrome, se aplicará el cambio.

Destacar que, en todo momento, el efecto del screen tearing es algo más pronunciado aquí que en Firefox.


[1]Un gestor de ventanas es el programa encargado de controlar la ubicación y apariencia de las ventanas.
[2]Un gestor de composición permite añadir efectos a las ventanas, tales como transparencias, sombras, animaciones…
comentarios vía Disqus