Which surface to use for eglMakeCurrent for the context that is only displayed in FBOs

I had the following situation:

In the cross-platform rendering library for iOS and Android (written in c (++)), I have two threads, each of which needs its own EGLContext: Thread A is the main thread; It displays a window. Thread B is a generator thread that performs various calculations and displays the results in textures, which are later used by thread A.

Since I cannot use EGL in iOS, the library uses function pointers for static Obj.-C functions to create a new context and set it to current. This already works, I create a context for thread A using

EAGLContext *contextA = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 

Context for thread B is created using

 EAGLContext *contextB = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[contextA sharegroup]]; 

Then I can set either of two current ones:

 [EAGLContext setCurrentContext:context]; 

To use the same logic (function pointers passed to the library) on Android, I want to do this on the C side of JNI bindings, this time using real EGL instead of Apple EAGL. I can easily create contextA using WindowSurface and my own window, I can create contextB and pass contextA to the shareContext parameter of the eglCreateContext call.

But when I want to create currentB current, I have to pass the surface to the eglMakeCurrent call, and I'm trying to figure out which surface should go there.

  • I cannot use WindowSurface for contextA, because the spec says in section 3.7 that “no more than one context for each supported API client can be current for a particular thread at a given time, and no more than one context can be attached to a specific surface in a given point in time.
  • I cannot specify EGL_NO_SURFACE because this will result in an EGL_BAD_MATCH error in the eglMakeCurrent call.
  • It seems that I could use the PBuffer surface, but I hesitate because I will need to specify the width and height when I create such a surface, and stream B can create textures of different sizes. In addition, the “OpenGL ES 2.0 Programming Guide” by Munshi, Ginsburg, and Shreiner says in section 3.8 that “Pbuffers are most often used to create texture maps. If all you want to do is display the texture, we recommend using objects framebuffer [...] instead of pbuffers because they are more efficient, "which is exactly what I want to do in stream B.

I don’t understand what Munshi, Ginsurg and Schreiner mean by this sentence, how will the framebuffer object replace the pbuffer surface? What if I create a very small (say 1x1px) pbuffer surface to make the context current - can I then map to arbitrarily large FBOs? Are there any other features that I still don't know about?

Many thanks for your help!

+6
source share
3 answers

As a result, I used the PBuffer surface (1x1 in size) - then I create the FBO and render in the textures just fine. To display them (in a different thread and in a different (general) opengl context), I use windowsurface with ANativeWindow (there is a sample of this somewhere in sdk).

+2
source

The surface that you pass eglMakeCurrent () must be the EGL surface of eglCreateWindowSurface (). For instance:

  EGLSurface EglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, maEGLconfigs[0], surfaceTexture, null); mEgl.eglMakeCurrent(mEglDisplay, EglSurface, EglSurface, mEglContext); 

But eglCreateWindowSurface () requires a SurfaceTexture, which is provided for the onSurfaceTextureAvailable () callback when creating a TextureView, but you can also create off-screen SurfaceTextures without any representation.

There is an example application that uses TextureView in the Android SDK here, although it uses a SurfaceTexture for a video camera and not for rendering OpenGL ES:

 sources\android-17\com\android\test\hwui\GLTextureViewActivity.java 

By default, the EGL surface for FBO will be the same size as the SurfaceTexture from which they were created. You can resize SurfaceTexture with:

  surfaceTexture.setDefaultBufferSize(width, height); 

Do not use pbuffers on Android, because some platforms (Nvidia Tegra) do not support them. This article details the benefits of FBOs over pbuffers:

http://processors.wiki.ti.com/index.php/Render_to_Texture_with_OpenGL_ES

+3
source

If drawing on FBO is the only thing you want to do, you can capture any EGLContext that you or someone else has already created (for example, GLSurfaceView) and make it current, then you just create your FBO, then draw with it . The problem is how to pass the context created by GLSurfaceView into your C ++ cross-platform library. I did this by calling a static function inside C ++ to get the eglcontext and surface right after the context became current using the Java level. For example, the code below:

 //This is a GLSurfaceView renderer method @override public void onSurfaceCreated(GL10 gl, EGLConfig config) { //up to this point, we know the EGLContext //has already been set current on this thread. //call JNI function to setup context graphics_library_setup_context(); } 

C ++ copy

 void setup_context() { context = eglGetCurrentContext(); display = eglGetCurrentDisplay(); surface = eglGetCurrentSurface(EGL_DRAW); } 
0
source

Source: https://habr.com/ru/post/946892/


All Articles