I'm trying to implement off-screen rendering with OpenGL ES on Android. My ultimate goal is to improve performance of texture mapping which I do in plain java and Bitmap/int[] APIs. I tried pbuffer approach, similar to the sample code from a relevant forum thread. It shows rather low performance, glReadPixels
call takes up to 50 ms on one device and up to 15 ms on another.
There is more modern approach using Frame Buffers. The code samples are rather complicated and I don't expect much faster transfer from Frame Buffer to Android's Bitmaps than it was with pbuffers. Am I right with my estimation?
The third approach is using pixmaps. If I understood the docs right they should utilize more sophisticated memory sharing between OpenGL and Dalvik's memory than plain copy. The problem is that relevant APIs aren't present in the Android SDK.
There is no eglCreateImageKHR
and EGLImageKHR
structure exposed in Java. All C++ examples I could find rely on them.
There is eglCreatePixmapSurface
but I can't figure out how to use it from the docs. Probably it receives some kind of bitmap handle in the native_pixmap
parameter, but I can't find any way to create such a handle. Searching for "eglCreatePixmapSurface android" leads only to problem reports.
My main question is: can I use pixmaps on Android from Java without writing native code? If I need to go native is there working code I can use to evaluate performance before diving deep into OpenGL?
Android includes support for high performance 2D and 3D graphics with the Open Graphics Library (OpenGL®), specifically, the OpenGL ES API. OpenGL is a cross-platform graphics API that specifies a standard software interface for 3D graphics processing hardware.
Android uses the OpenGL ES (GLES) API to render graphics. To create GLES contexts and provide a windowing system for GLES renderings, Android uses the EGL library. GLES calls render textured polygons, while EGL calls put renderings on screens.
The best way to improve texture loading performance on Android is to use the EGL image extensions you sited and EGL_NATIVE_BUFFER_ANDROID with native code. I have a code example of that in this article. I measured major performance improvements with this approach.
Android has no support for Pixmaps and pbuffers do not work on Nvidia Tegra devices. You should use FBO-attached textures instead. That is the way the Android SurfaceTexture class is implemented.
If you need alpha textures, that is another reason to use native code. There is a compatibility problem between Bitmap and OpenGL ES with alpha textures.
Using hardware texture compression formats (ETC/PVR instead of PNG) and mipmaps improves the loading performance and quality of texture rendering a lot too, as discussed in this article.
The big problem is glReadPixels(). EGL_NATIVE_BUFFER_ANDROID only works for writing textures, not for reading them back to a Bitmap. Android's platform code uses glReadPixels() to implement TextureView.getBitmap() and it is very slow. The best solution is to not copy the texture to a Bitmap, but to display the rendered TextureView directly which avoids glReadPixels().
I have been working with OpenGL ES 2.0 and the situation may have been improved with 3.0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With