【问题标题】:Android: GLSurfaceView is black after resuming appAndroid:恢复应用程序后 GLSurfaceView 为黑色
【发布时间】:2011-11-18 03:55:02
【问题描述】:

根据标题,GLSurfaceView 从暂停状态恢复后为空白。渲染器的onSurfaceCreatedonSurfaceChangedonDrawFrame 在恢复后被调用,但屏幕仍然是空白的!

以下是相关代码:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);

    boxWidth = 0.5f;
    boxHeight = 0.5f;
    boxCenter = new float[] { 0.5f, 0.5f };

    Log.v("resume", "onSurfaceCreated");
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {      
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0, 1, 0, 1, -5, 5);
    gl.glMatrixMode(GL10.GL_MODELVIEW);

    viewHeight = height;
    viewWidth = width;

    Log.v("resume", "onSurfaceChanged");
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glLoadIdentity();

    float halfW = boxWidth/2.0f;
    float halfH = boxHeight/2.0f;

    float left = Math.max(boxCenter[0]-halfW, 0.001f);
    float right = Math.min(boxCenter[0]+halfW, 0.999f);
    float top = Math.min(boxCenter[1]+halfH, 0.999f);
    float bottom = Math.max(boxCenter[1]-halfH, 0.001f);

    boxHeight = Math.max(top - bottom, 0.05f);
    boxWidth = Math.max(right - left, 0.05f);
    boxCenter[0] = left + boxWidth/2.0f;
    boxCenter[1] = bottom + boxHeight/2.0f;

    float vertices[] = {
            left, top, 0.0f,
            left, bottom, 0.0f,
            right, bottom, 0.0f,
            right, top, 0.0f
    };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);

    gl.glTranslatef(0.001f, -0.001f, -3.0f);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);

    vertexBuffer.position(0);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 
            vertexBuffer);

    gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

    gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    Log.v("resume", "drawing");
}

我了解到您需要在 onSurfaceChanged 中重新创建 GL 上下文,但我不确定如何,或者在调用 onSurfaceCreated 时我是否已经这样做了。

请帮忙!

编辑: 这是包含 GLSurfaceView 的 Activity 中的 onResume 代码:(此处称为 GLSurface)

public void onResume() {
   super.onResume();
   if (mGLSurface != null) {
   if (mRenderer != null) {
      float[] center = new float[2];
      center[0] = settings.getFloat("renderer_boxCenter0", 0.5f);
      center[1] = settings.getFloat("renderer_boxCenter1", 0.5f);
      mRenderer.setBoxCenter(center);
      mRenderer.setBoxWidth(settings.getFloat("renderer_boxWidth", 0.5f));
      mRenderer.setBoxHeight(settings.getFloat("renderer_boxHeight", 0.5f));
   }
   mGLSurface.onResume();
}

我在 GLSurfaceView 的 onResume 中没有做太多事情,也没有找到任何文档表明我需要做任何特别的事情来恢复我的 EGL 上下文。

编辑 2: 我还想指出,不幸的是,在 GLSurfaceView 的构造函数中调用 setPreserveEGLContextOnPause(true) 并没有解决我的问题。

【问题讨论】:

  • 也许发布您的 onResume() 代码以及您初始化和设置 GLSurfaceView 视图的位置
  • 尝试在 onSurfaceCreated 的末尾设置gl.glOrthof(0, 1, 0, 1, -5, 5);,看看第一次运行应用程序时是否出现任何内容。如果没有区别,请尝试在 onDraw 中设置gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);(即设置背景颜色为红色),然后在调用 onResume() 后将其更改为gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);(即蓝色)。这样你就可以判断 openGL 是否真的在响应你正在做的事情
  • 好的,我试过了。第一个建议没有任何区别。在第二种情况下,我看到蓝框在屏幕变黑之前短暂闪烁。你怎么看这个?
  • 我在你的问题中尝试了你所有的代码。它在我运行 android 2.1 的 ZTE Blade 以及 HTC Wildfire 和 Kindle Fire 上运行良好。但是我没有扩展 GLSurfaceView,所以问题出在您的 GLSurfaceView 代码中,而不是在您的渲染器或活动中
  • 我还尝试在运行 3.0 (API 11) 的模拟器和扩展的 GLSurfaceView 中使用每个方法(2 个构造函数,onPause 和 onResume)中的超级调用以及两个构造函数中的 setPreserveEGLContextOnPause(true)。再次工作正常

标签: android opengl-es onresume glsurfaceview


【解决方案1】:

setPreserveEGLContextOnPause(true) 仅在搭载 Android 3.X 及更高版本的设备上受支持。 (即便如此,是否支持也取决于设备)

您正在寻找的解决方案是在 GlSurfaceView 的父活动中,您在活动的 onPause 方法中调用 GlSurfaceView.onPause() 并在活动的 onResume 方法中调用 GlSurfaceView.onResume()。

请注意,这会导致您的所有纹理和缓冲区丢失。此时您需要重新加载它们。

【讨论】:

    【解决方案2】:

    这有点远,但您是否尝试控制方向或配置更改(即您是否有 public void onConfigurationChanged(Configuration config) 覆盖您的活动)?

    我发现如果我在我的活动中覆盖了 onConfigurationChanges() 并在我的清单文件中覆盖了 android:screenOrientation="landscape" 而不是 android:configChanges="orientation" 我会得到类似你描述的东西

    【讨论】:

    • 您好,我已强制我的应用程序仅以横向加载,尽管我实际上并没有覆盖 onConfigurationChanges()。我只是将android:screenOrientation="landscape" 放在我的清单文件中。
    • 尝试覆盖 onConfigurationChanges() 并在清单文件中添加相应的 configChanges="orientation" 并查看是否可以修复它,即使您只是从 onConfigurationChanges 调用 super 而实际上并没有在其中执行任何操作。它至少解决了我自己的应用程序的问题。不利的一面是,它确实会产生相当烦人的副作用,即在速度较慢的设备上,应用程序会在恢复后的几分之一秒内显示您应用程序的混乱纵向视图,然后才能正确切换到横向视图。
    • 您的意思是onConfigurationChanged()?我试图覆盖它并按照您的建议添加configChanges,但问题仍然存在。
    猜你喜欢
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多