android ANativeWindow_lock api不适用于GLSurfaceView

问题描述 投票:3回答:3

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

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

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

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

ANativeWindow api performance

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

我的程序:

  1. 将GLSurfaceView表面发送到jni代码。(使用GLSurfaceView.getHolder()。getSurface())**
  2. 使用ANativeWindow_fromSurface方法获取Window句柄。**
  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)

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

但总是它返回-22值。

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

是否可以将ANativeWindow_lock用于GLSurfaceView?

Here is my example code

任何帮助将非常感谢〜

android opengl-es android-ndk java-native-interface glsurfaceview
3个回答
0
投票

尝试这样做:

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

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


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);
}

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线程内

© www.soinside.com 2019 - 2024. All rights reserved.