Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Surface to use for eglMakeCurrent for context that only renders into FBOs

I'm having the following situation:

In a cross platform rendering library for iOS and Android (written in c(++)), i have two threads that each need their own EGLContext: Thread A is the main thread; it renders to the Window. Thread B is a generator thread, that does various calculations and renders the results into textures that are later used by thread A.

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

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

The context for thread B is created using

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

I can then set either of the two current:

[EAGLContext setCurrentContext:context];

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

But when i want to make contextB current, i have to pass a surface to the eglMakeCurrent call, and i'm trying to figure out what kind of surface to pass there.

  • I cannot use the WindowSurface i use for contextA as the spec says in section 3.7 that "At most one context for each supported client API may be current to a particular thread at a given time, and at most one context may be bound to a particular surface at a given time."
  • I cannot specify EGL_NO_SURFACE, because that would result in an EGL_BAD_MATCH error in the eglMakeCurrent call.
  • It seems I could use a PBuffer surface, but I hesitate because I'd have to specify the width and height when I create such a surface, and thread B might want to create textures of different sizes. In addition to that, the "OpenGL ES 2.0 Programming Guide" by Munshi, Ginsburg, and Shreiner states in section 3.8 that "Pbuffers are most often used for generating texture maps. If all you want to do is render to a texture, we recommend using framebuffer objects [...] instead of pbuffers because they are more efficient", which is exactly what i want to do in thread B.

I don't understand what Munshi, Ginsurg and Shreiner mean by that sentence, how would a framebuffer object be a replacement for a pbuffer surface? What if I create a very small (say 1x1px) pbuffer surface to make the context current - can i then still render into arbitrarily large FBOs? Are there any other possibilities I'm not yet aware of?

Thanks a lot for your help!

like image 952
Pontomedon Avatar asked Jun 09 '13 12:06

Pontomedon


2 Answers

The surface you pass to eglMakeCurrent() must be an EGL surface from eglCreateWindowSurface(). For example:

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

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

There is an example app that uses TextureView in the Android SDK here, although it uses the SurfaceTexture for camera video rather than OpenGL ES rendering:

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

By default, the EGL surface for FBOs will have the same size as the SurfaceTexture they were created from. You can change the size of a SurfaceTexture with:

    surfaceTexture.setDefaultBufferSize(width, height);

Don't use pbuffers on Android because some platforms (Nvidia Tegra) do not support them. This article explains the advantages of FBOs over pbuffers in detail:

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

like image 131
ClayMontgomery Avatar answered Oct 16 '22 14:10

ClayMontgomery


I ended up using a PBuffer surface (sized 1x1) - i then create an FBO and render into textures just fine. For displaying them (in a different thread and a different (shared) opengl context), i use a windowsurface with an ANativeWindow (there's a sample of that somewhere in the sdk).

like image 3
Pontomedon Avatar answered Oct 16 '22 16:10

Pontomedon