加载大纹理时内存溢出

时间:2013-04-25 07:04:47

标签: android opengl-es renderer glsurfaceview

我有一个GLSurfaceView和一个渲染器,用于在onSurfaceCreated中加载纹理。我的纹理是这样创建的:

public Texture3D(final GL10 gl, final int id) {
    _pBitmap = BitmapFactory.decodeResource(Utils.getResources(), id);
    gl.glEnable(GL10.GL_TEXTURE_2D);

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    texture = newTextureID(gl);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);


    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, _pBitmap, 0);

    _pBitmap.recycle();     
    _pBitmap = null;

    gl.glEnable(GL10.GL_BLEND);
}

我将它们存储在HashMap中:

textures.put(R.drawable.tile, new Texture3D(gl, R.drawable.tile));

我的问题是当我有时会出现以下错误后,从大图像(720x1280,561 Ko)创建纹理时:

04-24 11:05:19.870: D/dalvikvm(27953): GC_CONCURRENT freed 26K, 18% free 50397K/60743K, paused 18ms+6ms, total 57ms
04-24 11:05:19.870: D/dalvikvm(27953): WAIT_FOR_CONCURRENT_GC blocked 2ms
04-24 11:05:19.895: D/dalvikvm(27953): GC_FOR_ALLOC freed 7K, 18% free 50390K/60743K, paused 25ms, total 25ms
04-24 11:05:19.900: I/dalvikvm-heap(27953): Forcing collection of SoftReferences for 14745616-byte allocation
04-24 11:05:19.940: D/dalvikvm(27953): GC_BEFORE_OOM freed 10K, 18% free 50380K/60743K, paused 41ms, total 41ms
04-24 11:05:19.940: E/dalvikvm-heap(27953): Out of memory on a 14745616-byte allocation.
04-24 11:05:19.940: I/dalvikvm(27953): "GLThread 11210" prio=5 tid=35 RUNNABLE
04-24 11:05:19.940: I/dalvikvm(27953):   | group="main" sCount=0 dsCount=0 obj=0x42ec2008 self=0x6095d078
04-24 11:05:19.940: I/dalvikvm(27953):   | sysTid=29199 nice=0 sched=0/0 cgrp=apps handle=1623155456
04-24 11:05:19.940: I/dalvikvm(27953):   | schedstat=( 142147207 17456123 110 ) utm=11 stm=2 core=2
04-24 11:05:19.940: I/dalvikvm(27953):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
04-24 11:05:19.945: I/dalvikvm(27953):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
04-24 11:05:19.945: I/dalvikvm(27953):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:476)
04-24 11:05:19.945: I/dalvikvm(27953):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:499)
04-24 11:05:19.945: I/dalvikvm(27953):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:529)
04-24 11:05:19.945: I/dalvikvm(27953):   at com.gbanga.opengl.Texture3D.<init>(Texture3D.java:73)
04-24 11:05:19.945: I/dalvikvm(27953):   at com.gbanga.opengl.Texture3D.setupTextures(Texture3D.java:169)
04-24 11:05:19.945: I/dalvikvm(27953):   at com.gbanga.opengl.OpenGLRenderer.onSurfaceCreated(OpenGLRenderer.java:440)
04-24 11:05:19.950: I/dalvikvm(27953):   at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1494)
04-24 11:05:19.950: I/dalvikvm(27953):   at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

指向我使用BitmapFactory.decodeResource的构造函数的第一行。在我的Galaxy S3上,当我切换到另一个片段时,我收到错误,然后我回到显示GLSurfaceView的片段(onPauseonResume在{{1}上调用})。

我该如何避免这个问题?我尝试了this solution但是我失去了太多的质量,并且在极少数情况下,错误仍然发生(可能在旧手机型号上)。

我创建/存储纹理有什么问题吗?你也知道我为什么不总是得到这个错误? (通常我第二次加载纹理时会得到它。)

3 个答案:

答案 0 :(得分:2)

您熟悉:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html 较新的机器人有明确的参数:largeHeap = true

答案 1 :(得分:0)

您可以尝试通过从Android虚拟设备管理器编辑AVD来增加VM堆的大小...

答案 2 :(得分:0)

如果你的应用程序将处理大量纹理,并且如果你想支持旧型号手机,那么在本机上进行opengl处理可能更有利。

NDK中的hello-gl2示例显示了如何完成此操作。在本机方面,您将免受应用VM强制执行的限制(但您应该确保正确管理内存并且不会导致任何泄漏,因为即使用户关闭您的活动,该过程也会继续运行)