使用Android中的本机窗口进行分段错误

时间:2012-03-13 14:51:47

标签: android android-ndk opengl-es-2.0

我们正在尝试将C ++应用程序移植到Android。我们认为使用NativeActivity应该是最简单的,并且让所有OpenGL / EGL内容本地完成。

现在,我们通过应用程序传递我们从android_native_app_glue.h中的android_app结构获取的ANativeWindow指针,以便在初始化窗口时使用它。以下是此代码中的一些相关行(从调试代码中删除):

bool OpenGLWindowES::Initialize(EGLNativeWindowType wnd, EGLNativeDisplayType dsp,
                            EGLint redSize, EGLint greenSize, EGLint blueSize, EGLint             alphaSize, EGLint depthSize, bool bMultiSample)
{
    m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if(m_display == EGL_NO_DISPLAY)
    {
        return false;
    }

    EGLint iMajorVersion, iMinorVersion;
    if (!eglInitialize(m_display, &iMajorVersion, &iMinorVersion))
    {
        return false;
    }

    eglBindAPI(EGL_OPENGL_ES_API);
    bool ecc = eglChooseConfig(m_display, attribs, &m_config, 1, &iConfigs);
    if (!ecc || (iConfigs != 1))
    {
        return false;
    }

    EGLint format;
    eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format);
    ANativeWindow_setBuffersGeometry(wnd, 0, 0, format);
    m_windowSurface = eglCreateWindowSurface(m_display, m_config, wnd, NULL);
    //etc
}    

此代码继续创建上下文,makecurrent等,但我们没有那么远。我们在eglCreateWindowSurface上得到了一个分段错误,并且因为display和config似乎是正确初始化的,所以这只能意味着ANativeWindow *的问题(对于EGLNativeWindowType来说是tyepdef)。错误讯息:

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000058

如果我们调用例如:

,我们也会遇到分段错误
ANativeWindow_getHeight(wnd);

所以问题是,此时可能导致分段错误的原因是什么? wnd不是null,我们之前已经检查过了,所以它应该以某种方式进行初始化,并且应该可以使用了。在调用此函数之前我们是否遗漏了某些内容,或者指针有问题吗?

编辑:我们当前想知道这是否与APP_CMD_INIT_WINDOW命令没有正确发送或接收有关(我们还没有实现任何命令处理,所以我们正在研究这个)。

2 个答案:

答案 0 :(得分:1)

您是否完全确定窗口已正确初始化?

应用程序结构中的ANativeWindow指针在传递到本机入口点时不会自动设置。它由主Android线程稍后提供,然后通过app_glue设置的回调系统发送到应用程序。

你需要自己处理发送给android_app的调用,在NDK的native_activity示例中他们这样做:

int ident;
int events;
struct android_poll_source* source;

// If not animating, we will block forever waiting for events.
// If animating, we loop until all events are read, then continue
// to draw the next frame of animation.
while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
        (void**)&source)) >= 0) {

    // Process this event.
    if (source != NULL) {
        source->process(state, source);
    }
    ....
}

在主渲染循环中可能需要这样的东西,这将允许app_glue在从主线程获取窗口时自动正确设置窗口。

答案 1 :(得分:0)

问题是wnd,将state->window从主函数void android_main(struct android_app* state)传递到您的bool OpenGLWindowES::Initialize(...)方法作为第一个参数:

void android_main(struct android_app* state) {
    Initialize(state->window /*, other arguments here... */);
}