前几天在跑游戏引擎的时候,遇到了一个比较奇怪的问题,logcat不断地打印下面的错误:
waitForCondition(LockCondition) timed out (identity=23, status=0). CPU may be pegged. trying again.
更为奇怪的是,机器完全不能响应,最终重启,而且是可以100%重现的。
测试的机器是Moto ME525(MIUI 2.3.7)。
经过排查,发现与FBO的使用有关,引擎中对FBO使用的大概逻辑是:
@Override public void onDrawFrame(GL10 gl) { gl.glBindFramebuffer(GL10.GL_FRAMEBUFFER, 0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // here is some code that use fbo //gl.glBindFramebuffer(GL10.GL_FRAMEBUFFER, fbo); return; }
问题就出在,在return之前没有恢复到默认的FBO,解决起来也比较简单:
@Override public void onDrawFrame(GL10 gl) { gl.glBindFramebuffer(GL10.GL_FRAMEBUFFER, 0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // here is some code that use fbo //gl.glBindFramebuffer(GL10.GL_FRAMEBUFFER, fbo); // restore to the default fbo gl.glBindFramebuffer(GL10.GL_FRAMEBUFFER, 0); return; }
网上也有一些关于此问题的讨论,一部分人说是FBO的问题,一部分人说并非是FBO的问题;但我更相信是FBO的问题,理由如下:
先来看看GLSurfaceView中的一个代码片段
GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null) { view.mRenderer.onDrawFrame(gl); } int swapError = mEglHelper.swap();
报出错误日志的地方正是上面对swap的调用之处,而swap的功能正是交换前后缓冲区,而FBO显然是影响缓冲区的。