【问题标题】:Hardware accelerated double buffering on AndroidAndroid 上的硬件加速双缓冲
【发布时间】:2014-01-19 11:43:34
【问题描述】:

我们的应用程序需要双缓冲语义,例如在一次绘制操作中绘制一条线时,该线下一次应该仍然存在(不擦除,使用相同的缓冲区)。这对我们使用 SurfaceView、lock 等非常有效。

但是,那些cannot be hardware accelerated 和我们认为我们可能会错过某些 Android 设备上的某些性能。

在 iOS 上运行时,我们使用 OpenGL 并保留支持模式,以防止操作系统在每次重绘时擦除显示器。我希望 Android 有类似的东西可以防止无效调用擦除以前在屏幕上绘制的元素,但除了创建位图之外我找不到这样的选项。

绘制位图也是一种选择(这就是我们今天所做的),但是我们如何在这里利用硬件加速呢?

【问题讨论】:

  • OpenGLES 是寻找硬件加速最安全的方法。而且我可能大错特错,但我认为默认情况下启用了双缓冲,它与您所描述的无关。要在帧之间保留绘制的形状,在 onDrawFrame 中不调用 glClear() 就足够了(?)
  • 谢谢,但我对将代码移植到 OpenGL 不感兴趣,有很多代码,而 OGL 不是最适合这种类型的代码(大量文本等)。我们在 iOS 上使用 OGL,所以我很清楚我将面临的痛苦。
  • 双缓冲是为了防止由确实需要清除屏幕并从头开始绘制每一帧的应用程序引起的屏幕闪烁。您要求屏幕 被擦除,但另一方面您说您“需要双缓冲”。这听起来很矛盾;我会说完全禁用双缓冲,你应该很好。是我误解了这个问题,还是我错过了与我多年前使用的移动平台不同的 Android 某些内容?
  • 我上面的问题中的关键字:语义......我们需要语义而不是双缓冲本身。

标签: android performance hardware-acceleration


【解决方案1】:

我们在使用 Androidplot 库时遇到了类似的挑战,因为一次显示 2 个或更多 SurfaceView 的问题,我们排除了 SurfaceView 作为合法解决方案。我们最终创建了自己的BufferedCanvas 实现,它实际上只不过是一个使用位图的乒乓缓冲区。

就硬件加速而言,它应该默认启用,并且只要您不使用任何unsupported drawing operations,(据我所知)代码应该“正常工作”。您会注意到,出于这个原因,上面链接的代码必须明确禁用加速。

【讨论】:

  • 谢谢,不幸的是,据我了解,绘制位图将使用 CPU,因此只有 blit 部分会被硬件加速。这对于某些用例可能还不错,但我希望有更快的东西。
  • 明白了。 FWIW,您可以根据您使用的绘制方法排除渲染阶段的硬件加速。据我了解,如果您使用依赖其中任何一个,则需要删除它们或禁用加速。例如,如果您使用 clipRect 并希望支持 API 18 之前的任何内容,则不能使用它。这不是问题的解决方案,但也许它会让事情变得更简单
  • 编辑到上面:“......其中任何一个......”转换为“......任何不支持的绘图操作......”
  • 目标是拥有硬件加速并充分利用它。据我了解,大多数双缓冲策略都会有效地禁用硬件加速。
【解决方案2】:

不要绘制位图,坚持使用 OpenGL 并使用帧缓冲对象 (FBO)。

【讨论】:

  • 谢谢,但我不是在制作游戏。我需要做的很多工作是文本绘制,虽然它可以在 OGL 中完成(我们在 iOS 上这样做)这很糟糕。默认情况下(在 iOS 上)OGL 不会清除屏幕,但也不会保留它,尽管它有点离题。我不确定 Android 的情况如何,但我没有考虑采用开放 GL 路线。
  • 我在哪里说过游戏?你说你在你的 iOS 版本上使用 OpenGL,所以大概你的 Android 版本上的 OpenGL 是非常可行的,因为它是完全相同的 API。
  • 您仍然可以将文本绘制到位图,然后将位图渲染到 FBO。我假设重点是将所有昂贵的每帧文本渲染(可能不会每帧更改)减少到屏幕外缓冲区的单个 blit。
  • 在 iOS 上,我们使用 OpenGL,因为它是在那里执行任何高性能图形的唯一选择。这不是一个长远的想法。 iOS 代码依赖于 kEAGLDrawablePropertyRetainedBacking,这也不理想。
【解决方案3】:

这似乎不像双缓冲方法那样可行。

我最终做的是使用postInvalidate(int, int, int, int) 方法并构建一个任务队列来绘制已更改的元素。对我来说真正有问题的是Android一直在删除屏幕,这实际上是因为我们没有调用activity.getWindow().setBackgroundDrawable(null);,我们对软件渲染没有感觉,而是在硬件加速渲染中导致屏幕擦除。

【讨论】:

  • 只是为了让我理解正确(因为我可能面临类似的情况),如果在使用缓冲区 Bitmap 支持的 Canvas 上进行绘图调用,是否正确,那么硬件加速不会帮助将绘图操作转换为位图上的像素?这是在您的情况下避免使用缓冲区Bitmap 的原因吗? (换一种说法,从isHardwareAccelerated()返回true的唯一CanvasViewonDraw()中提供的那个吗?)
  • 据我了解是这样。可能以不同的方式获得硬件加速画布,但我找不到指向位图的硬件加速画布,这对我个人使用 OpenGL 的经验是有意义的。
猜你喜欢
  • 1970-01-01
  • 2011-12-13
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
相关资源
最近更新 更多