I am using OpenGL ES on Android using a GLSurfaceView and I want to be able to load textures on a separate thread to the render thread used by GLSurfaceView since I want to load textures on demand rather than loading them all in onSurfaceCreated.
Currently I load bitmap files on a background thread and then at the start of onDrawFrame if there are any bitmaps to load then GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0) is utilised, however this can cause some laggy behaviour.
Based upon some other articles I believe that I need to create an off-screen surface using eglCreatePbufferSurface with an associated thread separate to the thread used in the GLSurfaceView for rendering, but with a shared context being the EGLContext used by the rendering thread. This would enable me to have a dedicated thread for uploading textures but the context would be shared so then the rendering thread could access the uploaded textures.
Is this the correct way to approach this problem or am I misunderstanding what is required?
I have seen this post, which describes a similar issue: Threading textures load process for android opengl game but unfortunately it uses OpenGLES 1.0 and the example project doesn't seem to work. I have tried to modify it for OpenGLES 2.0 but I am unable to generate a texture, which suggests an issue with associating the EGLContext to the thread. I have also looked at the Grafika project, which has examples of creating a WindowSurface and an OffscreenSurface but I haven't seen these used together and probably need to migrate to using SurfaceView which if necessary is fine to do.
The basic approach is to create a secondary EGLContext in the same sharegroup as the original application context. You can create and upload textures in the secondary context, and use them in the primary context.
Importantly note that you will need to include synchronization between the contexts to ensure that the data upload to the texture has actually completed before the primary thread starts to use it. OpenGL ES provides automatic synchronization of the texture object state when bound, but not the data the texture contains.
Most modern devices allow a surfaceless context, so you may not need to allocate a dummy Pbuffer surface for context creation - YMMV here.
Related
I write Android game that using OpenGL ES 2.0. For example, a some game scene is drawing. How I can load another scene in background and when it loaded switch them. In background scene needs to load texture, generate their IDs and compile GL programs (shaders). But if I just create new Thread game crushes because game entities haven't access to GL context. And if I try to make it in GLSurfaceView.queueEvent get same error.
How I can do it? I found nothing by this theme.
P.S. Sorry for my English.
My advice is to keep the texture generation on the main thread.
Just do the image loading on a different thread.
Once the images are all loaded, notify the main thread, so that the main thread can do the actual creation of GL resources.
The file IO is probably slower than the actual gl texture creation anyway.
Also, for loading scenes, it pays to do the collision mesh generation on a helper thread, as that can be quite costly as well for large triangle meshes.
As we know, we can choose TextureView, SurfaceView and GLSurfaceView for android camera preview.
Which one is best choice for camera preview ? I'm focused on the camera performance.
From a performance perspective, SurfaceView is the winner.
With SurfaceView, frames come from the camera and are forwarded to the system graphics compositor (SurfaceFlinger) with no copying. In most cases, any scaling will be done by the display processor rather than the GPU, which means that instead of scanning the pixels once for scaling and again for scan-out, they're only scanned once.
GLSurfaceView is a SurfaceView with some wrapper classes that handle EGL setup and thread management. You can't use OpenGL ES on a Surface that is receiving camera frames, so you're doing extra work with no benefit. (The overhead is minor one-time setup, not per-frame, so you likely won't be able to measure the difference.)
TextureView receives the frames in a SurfaceTexture as an "external" OpenGL ES texture, then uses GLES to render them onto the app's UI surface. The scaling and rendering are performed by the GPU, and the result is then forwarded to SurfaceFlinger. This is the slowest option, but also the most flexible of the Views.
If you'd like to learn more about how the system works, see the Android Graphics Architecture document.
" The SurfaceView creates a new window in the Android Windowsystem. Its advantage is, that if the SurfaceView gets refreshed, only this window will be refreshed. If you additionally update UI Elements (which are in another window of the windowsystem), then both refresh operations block themselfes (especially when ui drawing is hardwaresupported) because opengl cannot handle multi thread drawing properly.
For such a case it could be better using the TextureView, cause it's not another window of the Android Windowsystem. so if you refresh your View, all UI elements get refreshed as well. (Probably) everything in one Thread.
Hope I could help some of you! "
Source : stackoverflow.com
GLSurfaceView is a SurfaceView with a wrapper class that does all the EGL setup and inter-thread messaging for you.
Its completely upto you what you put to use.. They have their pros and cons over eachother :)
I want to create a SurfaceTexture with an OpenGL texture that I can manage, in a setup similar to this answer. (Quoted here:)
Create a texture through OpenGL
Pass this texture to the constructor of new SurfaceTexture.
Give this new SurfaceTexture to the camera.
Make sure you are using OES_External (see documentation for
details).
However, creating an OpenGL texture (as in step 1 of the answer), requires an EGL context, which requires a EGLSurface to be made current, which requires a SurfaceTexture. It seems the only way of creating the EGL context is by creating a SurfaceView (or another view that has a SurfaceTexture), and use it to initialise the EGLSurface and then make the EGLContext current.
My objective is to create an EGLContext and make it current in a background thread, to do some offscreen computation on the camera preview image (mostly using the NDK). I want to create a library, and make it as independent of the UI as possible. Two related questions:
On the Java side, is it possible to create an EGLContext without having a SurfaceTexture created beforehand?
On the NDK side, there used to be a private API call to create native windows android_createDisplaySurface(), but it doesn't work anymore, and well, it's a private API. Is there any way of creating a surface with the NDK?
I'm quite new to using EGL, and I fail to understand why you need an EGLSurface for an EGLContext to be made current. In iOS, EAGLContexts can be created first, and then framebuffers can be created as needed. Using EGL it seems you always need a native window.
You can see a number of examples that manipulate Camera output, SurfaceTexture, and EGL in Grafika. The "Continuous capture" activity is one, but it uses the technique you mentioned: to avoid having to create an EGLSurface, it just borrows the one from the nearby SurfaceView.
You do need to have an EGLSurface, but it doesn't need to be a window surface. You can create a 1x1 pbuffer surface and just use that. This is done with the eglCreatePbufferSurface() call; see the EglCore class in Grafika for an example.
These examples are in Java, but the Java implementation just wraps the native EGL/GLES calls.
android_createDisplaySurface() is an internal call that, as you discovered, doesn't work on newer devices. Search the NDK for ANativeWindow instead.
Update: for anyone who gets here by searching, android_createDisplaySurface() relied on an internal class called FramebufferNativeWindow, which was marked obsolete in Android 5.0 in this change. The internal OpenGL ES test code that used it was updated with a SurfaceFlinger-based replacement in this change. The original version of the test code required shutting down the Android app framework so it could grab the frame buffer; the newer version just asks SurfaceFlinger for a window that covers the screen and is composited on top of everything else.
I want to have two threads. One thread writes into a texture using an FBO and the other uses it to render to the screen.
This can be done on windows etc, but how do I do it on Android?
I am using GL ES 2, and am using Textureview
I have read about the egl image extensions but I cannot figure out to use them
http://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image.txt
http://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
I read that the egl extensions are not fully supported on all platforms. Is it ok to use it on Android?
I cannot use something that is not assured to work properly.
This is what I read at this link:
http://www.khronos.org/message_boards/showthread.php/7319-EGLImage-on-Android-NDK
The EGL image extensions are not as necessary on Android now that the new TextureView class has been added with Android 4.0. Use TextureView to transfer texture images between OpenGL ES and the Canvas API.
I am using a TextureView. How do I use it to 'transfer texture images' ?
Also I read somewhere that egl defines textures as shared by default. What does this mean? How do I use the texture in a different context if it is already defined as shared?
I do not want to make the same context current in the other thread as I want the texture loading to be done without blocking the render to screen. Does this make sense?
I do not have much experience with OpenGL.
Apparently, firefox uses the same thing that I am trying to use
http://snorp.net/2011/12/16/android-direct-texture.html
But I can't understand how I should do it.
I am using Java, not NDK.
You have described the way OpenGL ES works on Android by default. In other words, you use the SurfaceTexture provided by TextureView to render OpenGL ES by one thread. Android's Surfaceflinger will then composite that SurfaceTexture to the display as part of it's normal View compositing - by another thread.
The EGL Image extensions are for getting pointers to the surfaces, which requires native code and is unnecessary. Use TextureView instead. There is an example app that uses TextureView in the Android SDK (although it uses the SurfaceTexture for camera video rather than OpenGL ES rendering):
sources\android-17\com\android\test\hwui\GLTextureViewActivity.java
So, use the SurfaceTexture (which is provided to the onSurfaceTextureAvailable() callback when the TextureView is created) to create the EGL Surface with eglCreateWindowSurface(). That SurfaceTexture will be the target of your OpenGL ES rendering and it will be displayed in the associated TextureView.
EGLSurface EglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null);
mEgl.eglMakeCurrent(mEglDisplay, EglSurface, EglSurface, mEglContext);
I think this article will help:
http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1
Can anyone tell me what the basic difference is between SurfaceView and GLSurfaceView? When should I use SurfaceView, and when should I use GLSurfaceView?
I read some already answered questions on Stack Overflow, but they did not satisfy my queries.
Any help would be appreciated.
A GLSurfaceView is a SurfaceView that you can render into with OpenGL. Choosing between them is simple:
If you're familiar with OpenGL and need what it provides, use a GLSurfaceView.
Otherwise, use a SurfaceView.
OpenGL is low-level. If you're not already familiar with it, it's an undertaking to learn. If you only need 2D drawing, SurfaceView uses the high-level, reasonably high-performance Canvas. It's very easy to work with.
Unless you have a strong reason to use a GLSurfaceView, you should use a regular SurfaceView. I would suggest that if you don't already know that you need GL, then you probably don't.
GLSurfaceView is the primary building block for 3D applications as View is for 2D applications. It is widely used not only in 3D games but also multimedia applications such as camera to create special preview affect.
GLSurfaceView extends SurfaceView and additionally owns a render thread and a render object set by the client. The render thread keeps running , continuously or on-demand, and delegates to the render object to draw frame using OpenGL API. For both SurfaceView and GLSurfaceView, rendering is performing in a separate thread other than main thread. The difference is with SurfaceView the rendering thread is created by client while with GLSurfaceView it is created by the system. What's more, GLSurfaceView will internally handle the synchronization between main thread and rendering thread.
For more, check out this and this
SurfaceView
AFAIK Canvas is Simple to implement and effective in 2D drawing but 3D drawing are not supported on it
GLSurfaceView
If you want to design some 3D Game then you shold go with GLSurfaceView and OGLES
Whats my experience is if you just want to do 2D processing then select Canvas because its easier to implement and effective compare to GLSurfaceView.