En la web abierta, Canvas y WebGL alimentan gráficas de velas, libros de órdenes en vivo y visualizaciones 3D de posiciones fluidas. Dentro de un WebView tiemblan o mueren. El WebView de Android cae a renderizado por software salvo que la aceleración de hardware esté activa a nivel de ventana — y canvas.getContext('webgl') devuelve null cuando no lo está. iOS mata en silencio el proceso GPU de WebKit bajo presión de memoria sin disparar webglcontextlost, así que la escena se pone negra mientras JavaScript sigue corriendo. Un runtime propiedad del host conecta el render nativo — las gráficas y visualizaciones se mantienen a 60fps en cada motor.
Android: renderizado por software por defecto, WebGL necesita la ventana
El WebView de Android admite dos modos: una capa de hardware que usa la GPU (requerida para WebGL) y una capa de software que usa la CPU. El tipo de capa por defecto es LAYER_TYPE_NONE, y lo crucial es que el WebView hereda el estado de aceleración de hardware de la ventana. Si la actividad o la ventana apaga la aceleración — un ajuste común en Unity/juegos/embebidos — el WebView cae en silencio a rasterización por CPU, y getContext('webgl2') / getContext('webgl') devuelve null. El arreglo no es solo android:hardwareAccelerated="true" en el manifest; la ventana del propio WebView debe estar acelerada, y setLayerType(LAYER_TYPE_HARDWARE, null) es la salida explícita. Incluso habilitado, la pérdida de contexto GPU al cambiar a segundo plano obliga a un redibujo explícito o aparece una pantalla negra.
iOS: el proceso GPU muere sin avisarte
En WKWebView el render corre en un proceso GPU de WebKit separado. Bajo presión de memoria iOS mata ese proceso — y no dispara webglcontextlost. La app sigue activa, JavaScript sigue corriendo, el HUD sigue vivo y la gráfica está negra. iOS 16+ también endureció los límites de WebGL: los recursos de origen cruzado (shaders y texturas en CDN) se bloquean por defecto con limitsNavigationsToAppBoundDomains = YES, forzando un downgrade a renderizado por CPU y caídas de frames visibles. El resultado práctico: una escena Three.js / PixiJS a 60fps en Safari se arrastra o se pone negra dentro del WebView.
Qué se rompe cuando el render tiembla
- Las velas y el libro de órdenes tiemblan. Las gráficas de velas, libros y tickers de los brokers pierden frames, así los traders leen precios obsoletos o retrasados.
- Posiciones y carteras 3D se congelan. Las visualizaciones WebGL de posiciones, superficies de riesgo y mapas se ponen negras al hacer scroll o bajo presión de memoria.
- Batería y calor se disparan. La rasterización por software de Canvas/WebGL en CPU consume batería y calienta el dispositivo.
- La trampa de "en mi escritorio funciona". Cada una de estas fallas solo aparece en el dispositivo, nunca en Chrome de escritorio.
La solución del runtime
Un runtime propiedad del host conecta la capa de render. Para visualización pesada el host ofrece una gráfica nativa / superficie GPU que la página controla vía runtime.renderChart() o una vista nativa; para Canvas/WebGL garantiza el contexto acelerado y maneja la recuperación de pérdida de contexto. La página conserva su código de gráficas declarativo; el runtime garantiza la GPU. Una integración, cada motor, un frame fluido al final.
| Dimensión | WebView | Runtime propiedad del host |
|---|---|---|
| WebGL Android | Downgrade por software; getContext('webgl') null si la ventana está apagada | Capa de hardware garantizada |
| GPU iOS | Proceso muerto, sin webglcontextlost | Superficie nativa + recuperación |
| Recursos de origen cruzado | Bloqueados por dominios app-bound | Carga nativa / empaquetada |
| Tasa de frames | Caídas, pantalla negra | Objetivo 60fps |
| Pérdida de contexto | Pantalla negra silenciosa | Observable, recuperable |
| Consistencia | Por motor | Uniforme |
Una app nativa renderiza sus gráficas en la GPU en cada dispositivo. Un WebView estándar en casi ninguno. Un runtime da a la página una ruta de render — y un frame en el que confiar.
Fuentes
- Android WebView — Aceleración de hardware y tipos de capa — el render de WebView depende del estado de aceleración de hardware de la ventana; el downgrade por software rompe WebGL.
- Android WebSettings — setLayerType / render por capas —
LAYER_TYPE_HARDWAREes la ruta explícita para habilitar la composición GPU para WebGL. - Apple Developer — WKWebView — WKWebView ejecuta WebKit en un proceso separado; iOS gestiona el proceso GPU bajo presión de memoria.
- DEV Community — Publicar un juego Three.js en iOS (muerte del proceso GPU) — iOS mata el proceso GPU de WKWebView sin disparar
webglcontextlost; el downgrade por software es silencioso. - CSDN — Rendimiento WebView Three.js / aceleración de hardware — Android WebView usa render por software por defecto; WebGL necesita
LAYER_TYPE_HARDWAREpara evitar contexto null.