通过Java API for GLES,在Android上使用像素图是否可行?

5
我正在尝试在Android上使用OpenGL ES实现屏幕外渲染。我的最终目标是改善我在纯Java和Bitmap/int[] API中进行的纹理映射的性能。我尝试了pbuffer方法,类似于相关论坛主题中的示例代码。它表现出相当低的性能,在一个设备上glReadPixels调用需要多达50毫秒,在另一个设备上需要多达15毫秒。
还有更现代的方法使用Frame Buffers。代码示例相当复杂,我不指望从Frame Buffer到Android的位图之间有比使用pbuffers更快的传输速度。我的估计正确吗?
第三种方法是使用像素图。如果我正确理解文档,它们应该利用OpenGL和Dalvik内存之间的更复杂的内存共享,而不是简单的复制。问题在于,相关的API不存在于Android SDK中。
在Java中没有eglCreateImageKHREGLImageKHR结构可供使用。所有我能找到的C++示例都依赖于它们。
eglCreatePixmapSurface但我无法从文档中弄清如何使用它。可能它在native_pixmap参数中接收一种位图句柄,但我找不到任何创建这样的句柄的方法。搜索"eglCreatePixmapSurface android"只会导致问题报告。
我的主要问题是:我是否可以在Java中使用像素图而不编写本机代码?如果需要进入本机代码,请问是否有可用的代码我可以使用以评估性能?
1个回答

6
在Android上提高纹理加载性能的最佳方法是使用您所提到的EGL图像扩展和带本地代码的EGL_NATIVE_BUFFER_ANDROID。我在这个article中有一个代码示例。采用这种方法可以显著提高性能。
Android不支持Pixmaps,pbuffers在Nvidia Tegra设备上不起作用。您应该改用FBO附加纹理。这就是Android SurfaceTexture类的实现方式。
如果需要alpha纹理,则使用本地代码是另一个原因。Bitmap和OpenGL ES之间存在兼容性问题,特别是涉及alpha纹理时。
使用硬件纹理压缩格式(ETC/PVR而不是PNG)和mipmaps也大大提高了纹理加载性能和渲染质量,正如article中所讨论的那样。
大问题在于glReadPixels()。EGL_NATIVE_BUFFER_ANDROID只适用于将纹理写入,而不适用于将其读取回位图。Android平台代码使用glReadPixels()来实现TextureView.getBitmap(),速度非常慢。最好的解决方案是不将纹理复制到位图中,而是直接显示渲染的TextureView,避免使用glReadPixels()。
我一直在使用OpenGL ES 2.0,情况可能已经在3.0中得到改善。

嘿,ClayMontgomery,我正在尝试使用gpuimage库进行一些图像处理任务。它运行良好,但是当使用大型图像时,速度会变慢。其中一个方法使用glReadPixels创建位图,这是瓶颈所在。有什么建议可以使它更快吗?我对opengl毫不了解。 https://github.com/CyberAgent/android-gpuimage/blob/febdf4900b437b2069661fd371d5469196e26f18/library/src/jp/co/cyberagent/android/gpuimage/PixelBuffer.java#L194 - Gaurav Vashisth
通过从本地代码而不是Java调用glReadPixels,可以将其时间缩短约30%,因为这样您就不必复制图像两次以将其放入位图中。但是,最好的解决方案是避免读取图像并直接显示它。 - ClayMontgomery
你好,ClayMontgomery。我本来在这里写一个问题给你,但最终我创建了一个全新的问题。如果你能看一下就太好了。 - focs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接