android: 8bit render target fallback when rgb10a2 window configs are non-conformant (#374) - #385
Conversation
…indow EGLConfig exists Some drivers (PowerVR BXE on Realtek TVs, wang-bin#374) expose RGBA_1010102 window configs but mark them all EGL_NON_CONFORMANT_CONFIG; rendering into one from a shared context corrupts the output. Probe once with eglChooseConfig (EGL_CONFIG_CAVEAT=EGL_NONE) and request depth=8 via setRenderAPI when the driver has no conformant 10bit window config. No behavior change on conformant drivers.
There was a problem hiding this comment.
Code Review
This pull request introduces a fallback mechanism to request an 8-bit render target on Android devices where the EGL driver lacks conformant 10-bit window configurations (which can cause output corruption on certain drivers like PowerVR BXE). This is achieved by linking against EGL, querying the available EGL configurations, and setting the GLRenderAPI depth to 8 if no conformant 10-bit configuration is found. The reviewer suggested calling eglTerminate after the EGL configuration probe to prevent potential resource leaks.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (!eglInitialize(dpy, &major, &minor)) // ref counted, no eglTerminate | ||
| return false; | ||
| const EGLint attrs[] = { | ||
| EGL_CONFIG_CAVEAT, EGL_NONE, // exclude slow/non-conformant configs | ||
| EGL_BUFFER_SIZE, 32, | ||
| EGL_RED_SIZE, 10, | ||
| EGL_GREEN_SIZE, 10, | ||
| EGL_BLUE_SIZE, 10, | ||
| EGL_ALPHA_SIZE, 2, | ||
| EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | 0x40/*EGL_OPENGL_ES3_BIT*/, | ||
| EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | ||
| EGL_NONE | ||
| }; | ||
| EGLint count = 0; | ||
| const EGLBoolean ok = eglChooseConfig(dpy, attrs, nullptr, 0, &count); | ||
| clog << "conformant rgb10a2 window EGLConfigs: " << count << endl; | ||
| return ok && count <= 0; |
There was a problem hiding this comment.
Although EGL initialization is reference-counted, failing to call eglTerminate after a successful eglInitialize can lead to resource leaks or prevent clean cleanup of EGL resources (especially if this is the only initialization of the display at this point). Since this is a one-time probe, it is best practice to call eglTerminate(dpy) to decrement the reference count back to its original state once the query is complete.
if (!eglInitialize(dpy, &major, &minor))
return false;
const EGLint attrs[] = {
EGL_CONFIG_CAVEAT, EGL_NONE, // exclude slow/non-conformant configs
EGL_BUFFER_SIZE, 32,
EGL_RED_SIZE, 10,
EGL_GREEN_SIZE, 10,
EGL_BLUE_SIZE, 10,
EGL_ALPHA_SIZE, 2,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | 0x40/*EGL_OPENGL_ES3_BIT*/,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
EGLint count = 0;
const EGLBoolean ok = eglChooseConfig(dpy, attrs, nullptr, 0, &count);
clog << "conformant rgb10a2 window EGLConfigs: " << count << endl;
eglTerminate(dpy);
return ok && count <= 0;There was a problem hiding this comment.
not calling eglTerminate here is intentional: this is the process-global default display shared with the flutter engine and mdk's own renderer in the same process, and per the EGL spec eglTerminate destroys ALL resources associated with the display — android's libEGL refcounts initialize/terminate, but on a spec-conformant implementation that call could tear down live contexts owned by other components. the display staying initialized for the process lifetime is the expected state, nothing is leaked. expanded the code comment in 1a44848 to document this
implements the detection from your #374 suggestion: probe once with eglChooseConfig (
EGL_CONFIG_CAVEAT = EGL_NONE+ 10/10/10/2 + window bit), and if the driver has no conformant 10bit window config, requestGLRenderAPI.depth = 8via setRenderAPI before updateNativeSurface. no context/surface created, cached after first call. no behavior change on drivers with conformant 10bit configstested on the #374 device (TCL google tv, PowerVR BXE, realtek RTD2875P, android 12) with the
EGL_SDR_DEPTHenv workaround removed:zero
IsTextureConsistenterrors, clean playback. ideally the caveat filter lives in libmdk's own eglChooseConfig (then this plugin-side fallback becomes redundant), but this fixes it for fvp users today(developed with an AI assistant (Fable), tested and verified on device)