Results 1 to 7 of 7

Thread: Loading textures in a background thread on Android

Hybrid View

  1. #1
    Newbie
    Join Date
    Jul 2013
    Posts
    3

    Question Loading textures in a background thread on Android

    I'm writing an Android application with OpenGL ES 2.0 that requires frequent texture loading and unloading. The optimal solution for me is to do this on a background thread to maintain responsiveness and to keep the architecture simple. It would also be easiest to handle everything in Java's GLSurfaceView; I'm trying to stay away from writing any native code.

    So with those constraints in mind, what's the right way to load textures on a non-render thread in Android? I've found surprisingly little information on this topic. I know I need a second EGLContext and that I probably have to bind it on the loading thread with eglMakeCurrent(). That call also requires EGLDisplay and EGLSurface objects. I know I can get the EGL object with EGLContext.getEGL(). With that, I can get the current context, display, and surface(s). Should it be as simple as getting these object references and then calling eglMakeCurrent() on the loading thread? Or is there more to it? Do i need to hook into the EGLContextFactory and EGLWindowSurfaceFactory? Do I actually need a second GLSurfaceView?

    Any direction you all can provide will be greatly appreciated.

  2. #2
    Member
    Join Date
    Jun 2012
    Location
    Texas
    Posts
    61
    Quote Originally Posted by suspense View Post
    I'm writing an Android application with OpenGL ES 2.0 that requires frequent texture loading and unloading. The optimal solution for me is to do this on a background thread to maintain responsiveness and to keep the architecture simple. It would also be easiest to handle everything in Java's GLSurfaceView; I'm trying to stay away from writing any native code.

    So with those constraints in mind, what's the right way to load textures on a non-render thread in Android? I've found surprisingly little information on this topic. I know I need a second EGLContext and that I probably have to bind it on the loading thread with eglMakeCurrent(). That call also requires EGLDisplay and EGLSurface objects. I know I can get the EGL object with EGLContext.getEGL(). With that, I can get the current context, display, and surface(s). Should it be as simple as getting these object references and then calling eglMakeCurrent() on the loading thread? Or is there more to it? Do i need to hook into the EGLContextFactory and EGLWindowSurfaceFactory? Do I actually need a second GLSurfaceView?

    Any direction you all can provide will be greatly appreciated.

    Android apps are normally required to execute all OpenGL ES calls from a single thread because EGL contexts can only be associated with a single thread and rendering graphics on the main UI thread is strongly discouraged. So the best approach is to create a separate thread specifically for all of your OpenGL ES code that will always execute from this same thread. If your app uses GLSurfaceView, it creates this dedicated OpenGL ES rendering thread automatically.

    Maybe it's possible for an Android app to have 2 EGL contexts open simultaneously, but I have not seen this done in Java apps. Obviously, it is done by the Android frameworks, such as the SurfaceFlinger. You would need to use TextureViews instead of GLSurfaceViews and create your own rendering threads. This is because each GLSurfaceView instance will have its own View in the hierarchy. TextureView is more flexible and uses SurfaceTextures which can be off-screen and it is possible to pass SurfaceTextures between threads.

    If you manage to get this working, please let us know. This article may help:

    http://software.intel.com/en-us/arti...cessors-part-1

  3. #3
    Newbie
    Join Date
    Jul 2013
    Posts
    3
    I've tried reimplementing the GLSurfaceView by copying the Android source for that class and building in the capability to create a second EGLContext and make it current. The app still runs, but when resources are loaded from the second EGLContext, they're not sharing OpenGL object names. For example, the main thread would generate textures 1-3, and then on the loading thread it would generate those some texture names again.

    From more searching on the web, it sounds like GL context sharing is just not available on many Android devices? I'm starting to feel like the hardware/driver situation on Android is just not ready for this kind of thing. It's hard to tell because some of the discussions I've found were several years old.

    I also tried replacing the GLSurfaceView with a TextureView, as detailed on a Stackoverflow discussion I can't link (really?) because I'm a new member here. When I got it running, the frame rate was only around 10 FPS. So I haven't gone any farther yet in that direction. Any ideas why the TextureView would have such poor performance?

  4. #4
    Member
    Join Date
    Jun 2012
    Location
    Texas
    Posts
    61
    Quote Originally Posted by suspense View Post
    I've tried reimplementing the GLSurfaceView by copying the Android source for that class and building in the capability to create a second EGLContext and make it current. The app still runs, but when resources are loaded from the second EGLContext, they're not sharing OpenGL object names. For example, the main thread would generate textures 1-3, and then on the loading thread it would generate those some texture names again.

    From more searching on the web, it sounds like GL context sharing is just not available on many Android devices? I'm starting to feel like the hardware/driver situation on Android is just not ready for this kind of thing. It's hard to tell because some of the discussions I've found were several years old.

    I also tried replacing the GLSurfaceView with a TextureView, as detailed on a Stackoverflow discussion I can't link (really?) because I'm a new member here. When I got it running, the frame rate was only around 10 FPS. So I haven't gone any farther yet in that direction. Any ideas why the TextureView would have such poor performance?
    I would expect the texture names to be duplicated, because they were allocated by different contexts.

    Google has never indicated that it's possible for an Android app to have more than one EGL context at a time, and they state that an EGL context can only ever be associated with a single thread. I think this is a limitation of the Android frameworks, not the EGL or OpenGL ES drivers, because this can be done on Linux.

    TextureView offers a lot more flexibility. For example, GLSurfaceView does not allow allocating surfaces which are off-screen, but TextureView does. The getBitmap() method of TextureView is slow because it uses glReadPixels(). But, Bitmaps should not be used for textures anyway because of the pre-multiplication problem. Otherwise, it will not affect the rendering performance.
    Last edited by ClayMontgomery; 07-11-2013 at 04:48 PM.

  5. #5
    Member
    Join Date
    Jun 2012
    Location
    Texas
    Posts
    61
    I just found an interesting discussion on StackOverflow that indicates that in newer versions of Android, they added EGL Context reference counting inside eglInitialize() and eglTerminate() to allow multiple components to use OpenGL ES and have several contexts open in an app simultaneously. Although, this seems to conflict with the EGL specification and is never mentioned in the Android documentation.

    http://stackoverflow.com/questions/6...egl-on-android

  6. #6
    Newbie
    Join Date
    Jul 2013
    Posts
    3
    Quote Originally Posted by ClayMontgomery View Post
    I would expect the texture names to be duplicated, because they were allocated by different contexts.
    My understanding was that if I pass the original context as a parameter in eglCreateContext, it would create a share group and the two contexts would then share object names and the associated resources. Is that not correct?

    Google has never indicated that it's possible for an Android app to have more than one EGL context at a time, and they state that an EGL context can only ever be associated with a single thread. I think this is a limitation of the Android frameworks, not the EGL or OpenGL ES drivers, because this can be done on Linux.
    So that explains why I've only seen working examples that use native code... they were using EGL directly instead of going through Android.

    I just found an interesting discussion on StackOverflow that indicates that in newer versions of Android, they added EGL Context reference counting inside eglInitialize() and eglTerminate() to allow multiple components to use OpenGL ES and have several contexts open in an app simultaneously.
    So this suggests I might be able to create two components (TextureViews / GLSurfaceViews) and pass the context from the first into the second to enable context sharing... Although if this does conflict with the spec it's probably something I shouldn't be doing in case the framework is made to conform with the spec in the future.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •