3

我正在寻找从 Android GLSurfaceView 快速获取绘图缓冲区的方法。

尽管我知道 glreadpixel 可以完成这项工作,但 glreadpixel 太慢而无法获得绘图缓冲区。

我想读取保持 30 fps 的缓冲区。

ANativeWindow api 似乎是我正在寻找的..

ANativeWindow api 性能

我找不到任何用于 GLSurfaceView 的 ANativeWindow api 示例。

我的程序:

  1. 将 GLSurfaceView 表面发送到 jni 代码。(使用 GLSurfaceView.getHolder().getSurface())**
  2. 使用 ANativeWindow_fromSurface 方法获取窗口句柄。**
  3. 设置窗口缓冲区**
  4. 锁定表面并获取窗口缓冲区**
  5. 使用此缓冲区做某事**
  6. UnlockAndPost 窗口**

我使用Android“BasicGLSurfaceView”示例尝试了下面的jni代码。

JNIEXPORT void JNICALL Java_com_example_android_basicglsurfaceview_BasicGLSurfaceViewActivity_readSurface(JNIEnv* jenv, jobject obj, jobject surface)
{

LOG_INFO("Java_com_example_android_basicglsurfaceview_BasicGLSurfaceViewActivity_readSurface");
if (surface != 0) {
    ANativeWindow *window = ANativeWindow_fromSurface(jenv, surface);
    LOG_INFO("Got window %p", window);
    if(window > 0)
    {
        int width = ANativeWindow_getWidth(window);
        int height = ANativeWindow_getHeight(window);

        LOG_INFO("Got window %d %d", width,height);

        ANativeWindow_setBuffersGeometry(window,0,0,WINDOW_FORMAT_RGBA_8888);

        ANativeWindow_Buffer buffer;
        memset((void*)&buffer,0,sizeof(buffer));

        int lockResult = -22;

            lockResult = ANativeWindow_lock(window, &buffer, NULL);
            if (lockResult == 0) {    \
              LOG_INFO("ANativeWindow_locked");
              ANativeWindow_unlockAndPost(window);
            }
            else
            {
                LOG_INFO("ANativeWindow_lock failed error %d",lockResult);
            }

        LOG_INFO("Releasing window");

        ANativeWindow_release(window);
    }


} else {
     LOG_INFO("surface is null");
}

return;

}

ANativeWindow_fromSurface 和 getHeight、setBuffersGeometry api 运行良好。

但是 ANativeWindow_lock api 总是无法返回 -22 值。

错误信息

[Surfaceview] 连接:已连接(cur=1,req=2)

我在渲染器或主线程或 onSurfaceChanged 的​​ onDrawFrame 上尝试了此代码。

但总是它返回 -22 值。

我在错误的地方调用这个 api?

是否可以将 ANativeWindow_lock 用于 GLSurfaceView?

这是我的示例代码

任何帮助将不胜感激~

4

3 回答 3

0

尝试这样做:

http://forums.arm.com/index.php?/topic/15782-glreadpixels/

希望您可以使用 ANativeWindow 作为缓冲区,这样您就不必直接调用 gralloc ...

于 2013-08-22T22:38:54.500 回答
0

我不确定memset是否需要该操作。

这对我有用:

ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
if(window > 0){
    unsigned char *data = ... // an RGBA(8888) image
    int32_t w = ANativeWindow_getWidth(window);
    int32_t h = ANativeWindow_getHeight(window);
    ANativeWindow_setBuffersGeometry(window, w, h, WINDOW_FORMAT_RGBA_8888);
    ANativeWindow_Buffer buffer;
    int lockResult = -1;
    lockResult = ANativeWindow_lock(window, &buffer, NULL);
    if(lockResult == 0){
        //write data
        memcpy(buffer.bits, data,  w * h * 4);
        ANativeWindow_unlockAndPost(window);
    }
    //free data...
    ANativeWindow_release(window);
}
于 2015-01-09T15:01:37.047 回答
0

当您遇到相同的错误信息时,

[Surfaceview] connect: already connected

您可以在调用本机部分之前通过 GLSurface.onPause() 解决此问题。您可以在本机代码中通过 ANativeWindow_lock、写入帧缓冲区、ANativeWindow_unlockAndPost 进行渲染。

// Java
SurfaceHolder holder  = mGLSurfaceView.getHolder();
mPreviewSurface  = holder.getSurface();
mGLSurfaceView.onPause();
camera.nativeSetPreviewDisplay(mPreviewSurface);

我只为发布 EGL 上下文调用 GLSurfaceView onPause()。GLSurfaceView 将由本机代码呈现。

GLSurfaceView

至少我认为这可以回答“是否可以将 ANativeWindow_lock 用于 GLSurfaceView?”这个问题。是的。

但是通过这种方式,您可以仅使用窗口缓冲区来渲染视图。您不能使用 opengl api,因为 GLSurfaceView.Renderer onDrawFrame() 在 GLSurfaceView 暂停后未被调用。它仍然显示出比使用更好的性能,但如果您需要 opengl api,它是无用的。

着色器调用应在 onSurfaceChanged()、onSurfaceCreated() 或 onDrawFrame() 的 GL 线程内

于 2017-04-18T03:09:34.880 回答