Android: Is it possible to create a SurfaceTexture

2020-02-25 11:37发布

I want to create a SurfaceTexture with an OpenGL texture that I can manage, in a setup similar to this answer. (Quoted here:)

  1. Create a texture through OpenGL
  2. Pass this texture to the constructor of new SurfaceTexture.
  3. Give this new SurfaceTexture to the camera.
  4. 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.

1条回答
够拽才男人
2楼-- · 2020-02-25 12:34

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.

查看更多
登录 后发表回答