Android绘图文本与几分钟后的opengl es崩溃

时间:2011-01-22 14:42:40

标签: android text opengl-es canvas frame-rate

我已经创建了一个opengl表面,一切正常,但是当我尝试使用以下方法在其上绘制文本时:

public void loadFPSTexture(GL10 gl){

    Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.RGB_565);
    bitmap.eraseColor(Color.BLACK);
    Canvas canvas = new Canvas(bitmap);

    Paint textPaint = new Paint();
    textPaint.setTextSize(35);
    textPaint.setFakeBoldText(true);
    textPaint.setAntiAlias(true);
    textPaint.setARGB(255, 255, 255, 255);
    canvas.drawText("FPS "+reportedFramerate, 10,35, textPaint);
    gl.glGenTextures(1, texturesFPS, 0);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesFPS[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle();
}

然后在我的onDraw函数中使用:

gl.glPushMatrix();
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesFPS[0]);
gl.glTranslatef(-surfaceSize.x/1.5f, surfaceSize.y/1.5f, 0.0f);
gl.glScalef(10, 10, 1.0f);
gl.glColor4f(1.0f, 1.0f, 1.0f, saturation_head); 
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureFPSBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glPopMatrix();

我得到一个奇怪的崩溃,在此之后无法绘制表面。 Logcat显示以下常量流:

E/Adreno200-EGL( 2578): eglLockWindowSurface: failed to map the memory for fd=32 offs=1536000
E/SurfaceFlinger( 2578): GL error 0x0505
E/Adreno200-EGL( 2578): eglLockWindowSurface: failed to map the memory for fd=32 offs=1536000
E/Adreno200-EGL( 2578): egliSwapWindowSurface: oglSwapBuffer failed
E/SurfaceFlinger( 2578): eglSwapBuffers: EGL error 0x3003 (EGL_BAD_ALLOC)

我不确定为什么会这样?任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:5)

麻烦的是我反复生成纹理而没有删除它们。只需在生成之前添加一行就足以防止内存泄漏(似乎无需检查是否已生成纹理):

 gl.glDeleteTextures(1, texturesFPS, 1);
 gl.glGenTextures(1, texturesFPS, 1);

简单如下:)

答案 1 :(得分:3)

看起来每次调用loadFPSTexture()时都会创建一个新纹理,并且永远不会释放它。一段时间后,这会导致内存不足,这可以解释日志中的EGL_BAD_ALLOC

最好只创建一次bitmapcanvastexturesFPS个变量,然后在loadFPSTexture()函数中重复使用它们。在这种情况下,您应该使用GLUtils.texSubImage2D()代替GLUtils.texImage2D(),将新的位图数据上传到现有纹理。

答案 2 :(得分:0)

我还没有评论访问权限(频繁的其他'帮助'网站,只是起床了),但想回应(和upvoted)svdree的说明,并添加更多细节 - 因为其他以GLES开头的人会肯定会遇到类似的问题。

无论您在哪里设置gles资源,都应创建一次您的位图,画布和纹理(以及绘图!)。清理应用程序的资源时,应删除它们。除非您正在调整位图/纹理的大小,否则重新创建会不必要地颠覆内存(cpu和gpu)。

最初创建纹理时,你要使用GLUtils.texImage2D函数来准备纹理(可以按原样上传位图,不关心数据)。这样可以确保纹理由驱动程序分配,适当的宽度/高度缓冲区可供以后更新。

渲染fps可能看起来更像:

s_bitmap.eraseColor(Color.BLACK);
s_canvas.drawText("FPS "+reportedFramerate, 10, 35, s_textPaint);
gl.glBindTexture(GL10.GL_TEXTURE_2D, s_texturesFPS[0]);
GLUtils.texSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, s_bitmap);

......就是这样。快一个数量级,显然更清洁。 : - )

你可以使它更快,例如只擦除/填充绘制fps的位图矩形,然后直接使用gl.glTexSubImage2D上传文本渲染的那些行(保存清除,并上传,说220个额外的数据行没有改变......)。

希望有所帮助!