2011-01-22 3 views
3

Я создал поверхность OPENGL и все работает нормально, однако, когда я пытаюсь нарисовать текст на него, используя следующий метод:текст Android Рисование с OpenGL ES аварии через несколько минут

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) 

Я не уверен, почему это происходит? Любая помощь приветствуется!

ответ

5

Проблема в том, что я неоднократно генерировал текстуры, не удаляя их. Просто добавив одну строку перед поколения достаточно, чтобы предотвратить утечку памяти (это, кажется, нет необходимости проверять, что текстура уже сгенерирован):

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

просто :)

+0

Не будет ли это «gl.glGenTextures (1, texturesFPS, 0)»; во второй строке? – Pedriyoo

3

Похоже, вы создаете новую текстуру каждый раз, когда вы вызываете loadFPSTexture() и никогда не выпускаете ее. Через некоторое время это приведет к тому, что у вас закончится нехватка памяти, что может объяснить EGL_BAD_ALLOC в ваших журналах.

Было бы лучше, чтобы создать bitmap, canvas и texturesFPS переменные только один раз, и использовать их в функции loadFPSTexture(). В этом случае вы, вероятно, должны использовать GLUtils.texSubImage2D() вместо GLUtils.texImage2D(), чтобы загрузить новые растровые данные в существующую текстуру.

+0

Попробуй это и сообщите, как это происходит. Я думал, что bitmap.recycle позаботится о выпуске использованной памяти.Я предполагаю, что текстура сделана, а затем, потому что она вне нормального GC (из-за буфера), она действительно не очищает текстуру? – stealthcopter

0

Я не» t еще есть доступ к комментариям (частые другие «справочные» сайты, просто встающие на SO), но хотели откликнуться (и сохранить) примечание svdree и добавить более подробную информацию - потому что другие люди, начиная с GLES, наверняка затронут аналогичные проблемы.

Ваше растровое изображение, холст и текстура (и краска!) Должны создаваться один раз, где бы вы ни настраивали свои ресурсы gles. Они должны быть удалены при очистке ресурсов для приложения. Если вы не изменяете размер растрового изображения/текстуры, воссоздание излишней памяти (CPU и gpu) излишне.

Первоначальное создание текстуры, вы должны использовать функцию GLUtils.texImage2D для подготовки текстуры (можно просто загрузить растровое изображение как есть, не заботятся о данных). Это гарантирует, что текстура выделяется драйвером, соответствующий буфер ширины/высоты готов для последующих обновлений.

Рендеринг кадров в секунду может затем выглядеть как:

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 дополнительных строк данных, которые не меняются ...).

Надеюсь, что это поможет!