android ANativeWindow_lock api不适用于GLSurfaceView

时间:2013-06-13 06:41:03

标签: android opengl-es android-ndk java-native-interface glsurfaceview

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

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

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

ANativeWindow api似乎就像我在寻找......

ANativeWindow api performance

我找不到任何关于GLSurfaceView的ANativeWindow api的例子。

我的程序:

  1. 将GLSurfaceView表面发送到jni代码。(使用GLSurfaceView.getHolder()。getSurface())**
  2. 使用ANativeWindow_fromSurface方法获取窗口句柄。**
  3. 设置窗口缓冲区**
  4. 锁定表面并获取窗口缓冲区**
  5. 使用此缓冲区执行某些操作**
  6. UnlockAndPost窗口**
  7. 我使用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)

    我在Renderer或主线程或onSurfaceChanged中的onDrawFrame上尝试了此代码。

    但始终返回-22值。

    我在错误的地方叫这个api?

    是否可以将ANativeWindow_lock用于GLSurfaceView?

    Here is my example code

    任何帮助都会非常感激〜

3 个答案:

答案 0 :(得分:0)

尝试这样做:

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

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

答案 1 :(得分: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);
}

答案 2 :(得分: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

至少我认为这可以解决问题“是否可以在GLSurfaceView中使用ANativeWindow_lock?”。 是的。

但是通过这种方式,您只能使用窗口缓冲区渲染视图。您不能使用opengl api,因为在GLSurfaceView暂停后不会调用GLSurfaceView.Renderer onDrawFrame()。它仍然表现出比使用更好的性能,但如果你需要opengl api它就没用了。

  

着色器调用应位于onSurfaceChanged(),onSurfaceCreated()或onDrawFrame()

的GL线程中