从 NDK 中获取 SurfaceTexture 的 GL 上下文
Grabbing SurfaceTexture's GL context from NDK
用途:
我正在使用 SurfaceTexture
来显示相机预览,并且需要通过从 NDK 获取 GL 上下文在表面上绘制。我选择了 SurfaceTexture
方法,因为我可以避免相机帧缓冲区的手动从 java 传递到 NDK,以节省一些性能。
public class MainActivity extends Activity implements SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(previewSize.width, previewSize.height, Gravity.CENTER));
try {
mCamera.setPreviewTexture(surface);
} catch (IOException t) {
}
mCamera.startPreview();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here
}
我试过的:
我想 SurfaceTexture
在内部使用 GL 功能来绘制上下文。从 NDK 获取默认显示失败并出现 BAD_DISPLAY
错误。
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
当然,我可以初始化一个新的 GL 上下文并进行绘图,但我仍然希望在后台显示 java 代码中的纹理。
问题: 使用 SurfaceTexture
时是否可以从 NDK 中获取 GL 上下文?
可能我必须在 GLSurfaceView
上使用,从 java 代码手动初始化 GL 上下文并从 NDK 中获取它?
你的问题对我来说并不完全有意义,所以让我列出一些事情。
SurfaceTexture 不绘制任何东西。当 Camera 作为生产者连接时,SurfaceTexture 接收 YUV 帧,并使用 EGL 函数将其设置为 "external" 纹理。然后您可以使用 GLES 渲染该纹理。
EGL 上下文一次可以 "current" 在一个线程中。指向当前上下文的指针保存在本机线程本地存储中。 Java 语言 GLES 绑定是本机代码的薄包装,因此在使用 GLES 时,Java 和 C++ 在概念上几乎没有区别。
SurfaceTexture 的纹理将与对象创建时的当前上下文相关联,但您可以使用 attach/detach 调用将其切换到不同的上下文。您不能 "grab" SurfaceTexture 的 EGL 上下文,但您可以告诉它您希望它使用哪一个。
SurfaceTexture(和一般的 Surface)只能有一个生产者。您不能将相机帧发送到您正在使用 GLES 渲染的表面。您可以在它们之间来回切换,但通常最好使用两个不同的 Surface 对象。
TextureView 是具有嵌入式 SurfaceTexture 的视图。当被要求重绘时,它使用 GLES 从纹理渲染(这就是为什么如果禁用硬件渲染你根本看不到任何东西)。
如果我没有正确理解你的问题,我认为你想要做的是:
- 将相机输出发送到在渲染器线程上创建的新 SurfaceTexture。
- 为 TextureView 的 SurfaceTexture 创建一个 EGLSurface。
- 使用 GLES 渲染到 TextureView,使用来自相机的纹理作为样本源。添加您想要的任何其他 GLES 渲染。
可以在 Grafika 中找到各种示例,例如"texture from camera" Activity.
用途:
我正在使用 SurfaceTexture
来显示相机预览,并且需要通过从 NDK 获取 GL 上下文在表面上绘制。我选择了 SurfaceTexture
方法,因为我可以避免相机帧缓冲区的手动从 java 传递到 NDK,以节省一些性能。
public class MainActivity extends Activity implements SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(previewSize.width, previewSize.height, Gravity.CENTER));
try {
mCamera.setPreviewTexture(surface);
} catch (IOException t) {
}
mCamera.startPreview();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here
}
我试过的:
我想 SurfaceTexture
在内部使用 GL 功能来绘制上下文。从 NDK 获取默认显示失败并出现 BAD_DISPLAY
错误。
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
当然,我可以初始化一个新的 GL 上下文并进行绘图,但我仍然希望在后台显示 java 代码中的纹理。
问题: 使用 SurfaceTexture
时是否可以从 NDK 中获取 GL 上下文?
可能我必须在 GLSurfaceView
上使用,从 java 代码手动初始化 GL 上下文并从 NDK 中获取它?
你的问题对我来说并不完全有意义,所以让我列出一些事情。
SurfaceTexture 不绘制任何东西。当 Camera 作为生产者连接时,SurfaceTexture 接收 YUV 帧,并使用 EGL 函数将其设置为 "external" 纹理。然后您可以使用 GLES 渲染该纹理。
EGL 上下文一次可以 "current" 在一个线程中。指向当前上下文的指针保存在本机线程本地存储中。 Java 语言 GLES 绑定是本机代码的薄包装,因此在使用 GLES 时,Java 和 C++ 在概念上几乎没有区别。
SurfaceTexture 的纹理将与对象创建时的当前上下文相关联,但您可以使用 attach/detach 调用将其切换到不同的上下文。您不能 "grab" SurfaceTexture 的 EGL 上下文,但您可以告诉它您希望它使用哪一个。
SurfaceTexture(和一般的 Surface)只能有一个生产者。您不能将相机帧发送到您正在使用 GLES 渲染的表面。您可以在它们之间来回切换,但通常最好使用两个不同的 Surface 对象。
TextureView 是具有嵌入式 SurfaceTexture 的视图。当被要求重绘时,它使用 GLES 从纹理渲染(这就是为什么如果禁用硬件渲染你根本看不到任何东西)。
如果我没有正确理解你的问题,我认为你想要做的是:
- 将相机输出发送到在渲染器线程上创建的新 SurfaceTexture。
- 为 TextureView 的 SurfaceTexture 创建一个 EGLSurface。
- 使用 GLES 渲染到 TextureView,使用来自相机的纹理作为样本源。添加您想要的任何其他 GLES 渲染。
可以在 Grafika 中找到各种示例,例如"texture from camera" Activity.