【问题标题】:Memory overflow when loading large textures加载大纹理时内存溢出
【发布时间】:2013-04-25 07:04:47
【问题描述】:

我有一个 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 的片段(onPauseonResumeGLSurfaceView 上调用)。

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

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

【问题讨论】:

  • 尝试增加虚拟机堆的大小。希望这能帮助您解决问题...
  • 我建议,尝试用MAT分析内存。 eclipse.org/mat

标签: android opengl-es renderer glsurfaceview


【解决方案1】:

你熟悉吗:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html 较新的 Android 具有清单参数:largeHeap=true

【讨论】:

  • 谢谢,我要看看这个,但这显然不适用于所有设备。我认为我需要专注于减少内存使用量。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    NDK 中的 hello-gl2 示例显示了如何做到这一点。在本机方面,您将不受应用虚拟机强制执行的限制(但是,您应该确保正确管理内存并且不会导致任何泄漏,因为即使用户关闭您的活动,该进程也会继续运行)

    【讨论】:

    • 好的,谢谢你的提示,这可能是我最后的选择,因为我需要重新编码所有内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 2014-08-31
    • 1970-01-01
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多