본문 바로가기

나의 플랫폼/안드로이드

[ Android Opengl es 2.0 ] LiveWallpaper 에서 사용 시 , onSurfaceCreated 문제

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 이 문제는 제가 코딩을 잘못 하거나, 샘플 소스를 잘못 이용한 걸 수도 있지만,
경험의 유추했을 때 결론이 나와. 이렇게 글을 남깁니다.
혹시 잘못된 부분이 있으면 주저 말고 댓글을 달아주시면 감사하겠습니다.^^ 



 Opengl es 2.0을 사용하여 개발하는 중.. 화면을 껏다가 다시 켜면..
뭔가 속도가 느려지다가 결국 Out of memory 오류와 함께 팅겨져 버립니다.

역시나 Out of memory 부분은 Texture 부분이 문제 이죠.

onSurfaceCreated 함수 내에 Texture를 셋팅 하는 소스를 코딩하였습니다.

loadTexture ( mContext.getResources().openRawResource( R.raw.background) ,"mBgTexId" );


디버깅을 해본 결과... 예전 Opengl es 1.1에서는 화면을 갱신 해도, onSurfaceCreated 함수가 불러지지 않았었습니다.

하지만, Opengl es 2.0으로 바뀌면서 static 메모리 함수로 바뀌고 나서
GLES20와 관련된 메모리 장치들이 초기화가 되는 것 같습니다.
더 웃긴 건... 초기화가 되면서, 메모리 Texture 버퍼들이 삭제가 되지 않는 점입니다.

결국.. 프로그램 실행 시 , 한번만 실행이 되었던 onSurfaceCreated 함수내에 예외 처리가 필요했습니다.

deleteTexture(texId);

texId = loadTexture ( mContext.getResources().openRawResource( R.raw.background) ,"mBgTexId" );

private void deleteTexture(int texId){
    // 전에 저장되어 있는 texture 가 있는지 확인
    
if(texId == 0)

    return;
 

    int idArr[];

    IntBuffer intbuf;

    idArr = new int[]{texId};

    intbuf = getIntBufferFromIntArray(idArr);

    GLES20.glDeleteTextures(1, intbuf);

 }

 


 이렇게 계속 갱신 할때마다 Texture를 불러 올 경우, 매번 이미지를 불러와야 하므로 속도가 느려집니다.
결국, TextureBuffer를 저장 시켜놓고, 갱신 할때마다 TextureBuffer를 이용하는 쪽으로 수정하였습니다.
이럴 경우, Texture 설정 시간이 조금 걸리지만 그리 느려지는 현상이 줄어듭니다.

private int loadTexture ( InputStream is ,String strKey)

    {

        int[] textureId = new int[1]; 
        // 기존의 존재하는지 확인

        if(texBuffer.get(strKey) == null){

        TexValue value = new TexValue();

       

       Bitmap bitmap;

       bitmap = BitmapFactory.decodeStream(is);

       bitmap = Bitmap.createScaledBitmap(bitmap,getMinPowerByTwo(bitmap.getWidth()), getMinPowerByTwo(bitmap.getHeight()),false);

       

   ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bitmap.getWidth() * bitmap.getHeight() * 4);

   byteBuffer.order(ByteOrder.BIG_ENDIAN);

   IntBuffer ib = byteBuffer.asIntBuffer();

   

   int bitmapWidth = bitmap.getWidth();

   int bitmapHeight = bitmap.getHeight();

   

   int[] pixels = new int[bitmapWidth * bitmapHeight];

   bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

   bitmap.recycle();

   bitmap = null;

   

   for(int i=0; i<pixels.length; i++){

       ib.put(pixels[i] << 8 | pixels[i] >>> 24);

   }

   value.bmpWidth = bitmapWidth;

   value.bmpHeight = bitmapHeight;

   value.texBuffer = byteBuffer;
                    // Buffer를 저장 시켜 놓는다.

   texBuffer.put(strKey,value);

        }

        texBuffer.get(strKey).texBuffer.position(0);

   GLES20.glGenTextures ( 1, textureId, 0 );

   GLES20.glBindTexture ( GLES20.GL_TEXTURE_2D, textureId[0] );

 

   GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );

   GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );

   GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );

   GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );

   

   GLES20.glTexImage2D ( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texBuffer.get(strKey).bmpWidth, texBuffer.get(strKey).bmpHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer.get(strKey).texBuffer );

   

   return textureId[0];

    }


지금 이건 저의 경험을 토대로 나온 것들입니다.

뭔가 문제가 있다고 생각되시면 언제든지! 꼭! 댓글 부탁드립니다.

감사합니다.