绘制path和硬件加速

在我看来,我正在绘制一条相当大的路,而且我遇到了一些性能问题。 目前的path是32000点,但我的应用程序应该扩展到至less128000点。 对于path的大小,我无法做任何事情,因为数据集非常大,我需要能够一次显示整个path并允许放大。

我使用的是运行Android 4.2的Nexus 10,默认情况下硬件加速function是针对未明确禁用的应用程序启用的。

path是用下面的代码创build的(我省略了一些设置和其他不相关的部分):

dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor); for (int i = leftLimit; i < rightLimit; ++i) { x = (i - leftLimit) * dx; y = offset - (float) data[i]/ scalingFactor; dataPath.lineTo(x, y); } 

然后在onDraw()方法中绘制:

 canvas.drawColor(Color.WHITE); canvas.drawPath(dataPath, linePaint); 

我测量了使用adb shell dumpsys gfxinfo来绘制我的视图所花费的时间,而且没有硬件加速,我惊讶地发现硬件加速比较慢:

随着硬件加速:

在这里输入图像说明

没有硬件加速:

在这里输入图像说明

硬件加速版本每帧需要大约200-300毫秒,大部分花费在处理阶段。 非加速版本大约需要50 ms,Draw阶段为2/3,处理阶段为1/3。

显然,即使我没有硬件加速的更快的版本仍然太慢,达不到60fps,或者当我移动到更大的数据集时甚至几乎无法使用。

将path渲染为位图,然后仅将该位图转换为适合屏幕的想法在我的情况下也是有问题的。 我需要支持非常远的path放大,并启用放大,没有path质量变得更糟,我将不得不渲染超大的path位图(并可能会遇到内存限制和纹理尺寸限制)。 而当放大的时候,我不得不创build只有部分path的更新的图像,或者直接渲染path,这可能会导致比帧速率更大的延迟,如果性能仍然类似于我所说的现在。

我现在想知道的是

  • 绘制线条/path只是GPU的坏处,而不应该尝试硬件加速,或者我可能做错了什么导致了糟糕的performance?
  • 我能做些什么来画出如此巨大的道路,performance可以接受吗?

绘制线条/path只是GPU的坏处,而不应该尝试硬件加速,或者我可能做错了什么导致了糟糕的performance?

path总是使用CPU呈现。 当应用程序被硬件加速时,这意味着渲染器将首先使用CPU将您的path绘制到位图中,然后将该位图作为纹理上传到GPU,最后在屏幕上绘制纹理。

线路完全是硬件加速的。 在这种情况下,我build议使用Canvas.drawLines()来代替使用Path

我能做些什么来画出如此巨大的道路,performance可以接受吗?

你应该使用Canvas.drawLines()或者将自己的path渲染到你pipe理的Bitmap中。

看起来你可能会遇到GPU的一般瓶颈。 看看下面的链接:

如何使路线绘制更有效率

Androidcanvaspath的实时性能

从canvas切换到OpenGL

特别是第一个,它build议你制作一个位图并绘制。 看起来你可以得到更好的性能,如果你改变为OpenGL。 现有的方法工作可能有一些神奇的方法,但我现在还没有意识到这一点。

为什么你看到你所做的行为可能是因为你在每次绘制之间把所有的数据发送到GPU。 您应该将其caching在GPU上,并使用翻译。 不重新创build数据并将其全部发送到GPU。 你可能是I / O绑定的 ,这意味着CPU和GPU之间的传输速率是限制你的性能。 根据你所提供的数据,我不能百分之百地确定这一点,但这是我最好的猜测。 尝试不同的caching技术,主要是链接#1中的pngcaching。

绘制一条path不仅仅是“告诉”GPU绘制线条。 path具有许多特征,例如线条的末端如何处理或线条是否点缀,而不是 GPU加速。 当你遇到许多使CPU和GPU加速的组合变慢的行时,可能会出现另一个混乱。 上面build议的解决scheme移动到canvas.drawLines而不是canvs.drawPath并尝试不使用花哨的Paint方法可能会有所帮助。

如果这没有帮助,你可以尝试使用GLSurfaceView并直接渲染线代替。 这将涉及到一些OpenGL ES的知识,但不应该是难以置信的,可能会更有效。