问题
I have a problem that occours only with the latest Samsung Galaxy series when android:hardwareAccelerated is set to false into manifest file
As far as i know (tried by myself) it happens on Galaxy S9, J6 and Note 8 but not on Galaxy S8 for example. Other phones seem not affected at all.
The problem is that i got a GLSurfaceView that shows nothing (black screen) but if i switch between activities, it start to work again, i guess because it renews the View with no errors.
This is the suspect log lines i've found
01-13 14:39:47.813 25013 25080 E libEGL : eglCreateWindowSurface: native_window_api_connect (win=0xc166b808) failed (0xffffffed) (already connected to another API?)
01-13 14:39:47.813 25013 25080 E libEGL : eglCreateWindowSurface:679 error 3003 (EGL_BAD_ALLOC)
and these are the crucial part of my code:
GLSurf glsurf;
public void onPause() {
super.onPause();
// stop
if (glsurf != null) {
glsurf.onPause();
}
}
@Override
public void onResume() {
super.onResume();
if (glsurf != null)
glsurf.onResume();
}
public class GLSurf extends GLSurfaceView {
public GLSurf(Context context) {
super(context);
/* Create an OpenGL ES 2.0 context. */
setEGLContextClientVersion(2);
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
// Set the Renderer for drawing on the GLSurfaceView
mRenderer = new GLRenderer(context);
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
}
public class GLRenderer implements Renderer {
GLRenderer(Context c){
// does nothing
}
@Override
public void onDrawFrame(GL10 unused) {
// i've copied it but it's not even reached
// call jni function updating the single texture filling the screen
nativeGLRender();
// Draw the triangles
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// We need to know the current width and height.
mScreenWidth = width;
mScreenHeight = height;
// Redo the Viewport.
GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the clear color to black
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);
}
}
Some info more:
the EGL_BAD_ALLOC occours always after this sequence of events with meaningful (at least i think) logs
onCreate
onResume
onPause
GLSurfaceView: Warning, !readyToDraw() but waiting for draw finished! Early reporting draw finished.
onResume
libEGL : eglCreateWindowSurface: native_window_api_connect (win=0xc166b808) failed (0xffffffed) (already connected to another API?)
libEGL : eglCreateWindowSurface:679 error 3003 (EGL_BAD_ALLOC)
onPause
onStop
onDestroy
onCreate
onResume
onSurfaceCreated
: NULL == surf->write_back_color_buffer
: NULL == surf->write_back_color_buffer
GLThread: eglSwapBuffers failed: EGL_BAD_SURFACE
... black screen ...
Please note that above events occour with no user interaction and in a span of 1-2 seconds. Any idea about what's going on?
For completion of infos, the following is the sequence of a working phone (e.g. my nexus 6)
onCreate
onResume
onSurfaceCreated
... working screen
Edit Jan 16th:
New informations about the issue:
- When the app starts for the first time, it works
- Never work on the next tries
- It works if put in background and restored
- The error never happen if i put android:hardwareAccelerated to true (but i cannot turn it on for other reasons)
Edit Jan 18th
- I forgot to mention that the issue occours only if android:hardwareAccelerated is set to false
I ALSO FOUND THE REASON OF THE BUG
Don't know why, but i just changed this part of code
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
getWindow().setFormat(PixelFormat.RGB_565);
}
with this
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
}
and everything went ok. A bug in Samsung drivers? Maybe...
I hope this could be useful for somebody
回答1:
eglCreateWindowSurface: native_window_api_connect failed Any idea about what's going on?
The problem viewed from logcat perspective
The called function from eglApi.cpp is:
/*
* native_window_api_connect(..., int api)
* connects an API to this window. only one API can be connected at a time.
* Returns -EINVAL if for some reason the window cannot be connected, which
* can happen if it's connected to some other API.
*/
static inline int native_window_api_connect(
struct ANativeWindow* window, int api)
{
return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
}
Here is a comment block from the WindowSurface.recreate()
from WindowSurface.java method that says:
/*
* If the previous EGLSurface isn't fully destroyed, e.g. it's still current on a
* context somewhere, the create call will fail with complaints from the Surface
* about already being connected.
*/
Related problem
Opengls eglCreateWindowSurface GL Error EGL_BAD_ALLOC from Jitesh Dalsaniya:
I solved error GL Error EGL_BAD_ALLOC. This error occurs due to I am not handling Renderer properly with activity life cycle.
Activity Life-cycle
A
GLSurfaceView
must be notified when to pause and resume rendering.GLSurfaceView
clients are required to callonPause()
when the activity stops andonResume()
when the activity starts. These calls allowGLSurfaceView
to pause and resume the rendering thread, and also allowGLSurfaceView
to release and recreate theOpenGL
display.
EGL Context Lost
There are situations where the
EGL
rendering context will be lost. This typically happens when device wakes up after going to sleep. When theEGL
context is lost, allOpenGL
resources (such as textures) that are associated with thatcontext
will be automatically deleted. In order to keep rendering correctly, a renderer must recreate any lost resources that it still needs. TheonSurfaceCreated
(GL10, EGLConfig) method is a convenient place to do this.
Workaround-to-losing-the-opengl-context-when-android-pauses
So your Activity's
onPause()
should look like this:
@Override
public void onPause() {
glsurf.setVisibility(View.GONE);
super.onPause();
...
}
And you restore your GLSurfaceView
to the hierarchy not from onResume()
but from onWindowFocusChanged()
:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && glsurf.getVisibility() == View.GONE) {
glsurf.setVisibility(View.VISIBLE);
}
...
}
Other things to try
- You'd need to debug to figure out why it's unhappy.
- Try use
OpenglView
Visible always andstartPreview
when you get permissions. An invisible holder is not valid for opengl and this could cause your crash. - Bad release of Opengl ?
- Handle
onSurfaceTextureSizeChanged
inTextureViewGLActivity
? EGL_BAD_ALLOC
andeglSwapBuffers failed:
EGL_BAD_SURFACE
is a big clue...!readyToDraw()
delete and recreate the Surface ?
Further
Observation:
The error never happen if I put
android:hardwareAccelerated
to trueHardware acceleration is enabled by default if your
Target API
levelis >=14
, but can also be explicitly enabled (at the Application or Activity level).
Document Links
GLSurfaceView, GLSurfaceView.Renderer, hardware-acceleration
回答2:
Calling glsurf.setVisibility(View.GONE)
in onPause()
works for my app, but it won't work when I call glsurf.setVisibility(View.VISIBLE)
in onWindowFocusChanged()
.
It works for me when I call glsurf.setVisibility(View.VISIBLE)
in onResume()
.
来源:https://stackoverflow.com/questions/54183090/eglcreatewindowsurface-native-window-api-connect-failed