3

我创建了一个 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)

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

4

3 回答 3

5

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

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

就那么简单 :)

于 2011-02-28T16:05:57.203 回答
3

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

最好只创建一次bitmap,canvas和变量,然后在() 函数texturesFPS中重用它们。loadFPSTexture在这种情况下,您可能应该使用GLUtils.texSubImage2D()而不是GLUtils.texImage2D(), 将新的位图数据上传到现有纹理。

于 2011-01-22T15:39:29.153 回答
0

我还没有评论访问权限(经常使用其他“帮助”网站,只是开始使用 SO),但想回应(并赞成)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 行没有变化的额外数据......)。

希望有帮助!

于 2011-08-24T17:14:23.313 回答