【问题标题】:E/libEGL: call to OpenGL ES API with no current context (logged once per thread) - Android/SDLE/libEGL:在没有当前上下文的情况下调用 OpenGL ES API(每个线程记录一次)-Android/SDL
【发布时间】:2017-06-18 00:10:27
【问题描述】:

我知道之前已经回答了这个问题的不同版本,并且我已经阅读了很多。然而似乎没有人能帮助我解决我的问题。

我正在使用 SDL 创建一个上下文来保存 OpenGL ES。如果我从包含当前上下文的线程进行 OpenGL ES 调用,我可以正常渲染。但是,如果我从另一个线程进行 OpenGL ES 调用,我将无法进行任何渲染,并且我会在标题中收到错误消息。

E/libEGL: call to OpenGL ES API with no current context (logged once per thread)

我使用的是 SDL 源码包中提供的 android 项目模板。这使用一个名为 SDLActivity 的类与 android 和本机 c/c++ 代码进行通信。

问题是如何创建多个 SDL 上下文,以便我仍然可以从另一个线程进行 OpenGL ES 调用?

编辑:这是我在代码中创建 SDL 上下文的地方:

    int SDL_main(int argc, char **argv)
    {
       window = nullptr;

       if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
          return false;


       SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
       SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
       SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

       SDL_DisplayMode currentDisplayMode;
       int success = SDL_GetCurrentDisplayMode(0, &currentDisplayMode);
       assert(success == 0);
       WIDTH = currentDisplayMode.w;
       HEIGHT = currentDisplayMode.h;

        window = SDL_CreateWindow(Name.c_str(),
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
        assert(window != nullptr);

        SDL_SetHint("SDL_HINT_ORIENTATIONS", "LandscapeRight LandscapeLeft");

        context = SDL_GL_CreateContext(window);
        assert(context != nullptr);

    glGetError();   

    //OpenGL configuration
    glViewport(0, 0, WIDTH, HEIGHT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //initialise 

    obj.functionA();

    obj.functionB();    

    SDL_SetEventFilter(FilteringEvents, NULL);



    SDL_Event event;
    shouldQuit = false; 
    while (!shouldQuit)
    {
        SDL_PollEvent(event);

        //Render
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);


        obj.Render();

        SDL_GL_SwapWindow(window);

    }

    SDL_Quit();

    return 0;
}

为了简单起见,我只包括了通过 SDL 创建 Opengl ES 的上下文,以及一些简单的 obj 函数调用,例如对渲染的调用。

如您所见,渲染调用是在 SDL 创建的 OpenGL 上下文的线程中进行的。那么如何使用 SDL 创建共享上下文,因为当我在这个线程之外进行 OpenGL ES 调用时,我得到了错误。请注意,当我在我的 PC 上运行相同的代码时,我没有遇到这个问题,所以我确定这是 Android 特有的问题。

【问题讨论】:

    标签: android c++ multithreading opengl-es sdl


    【解决方案1】:

    传统上,OpenGL ES 应用程序只从一个线程渲染到一个表面。

    渲染线程是与一个图形上下文相关联的一个 CPU 线程。默认情况下,每个图形上下文将无法访问另一个上下文的资源(纹理、着色器和顶点缓冲区)。出于这个原因,使用了共享上下文,以便一个或多个后台加载线程可以访问主线程的资源。

    我认为您的问题是 EGL 渲染上下文未绑定到当前渲染线程。

    看看eglCreateContext 了解如何制作共享上下文,看看eglMakeCurrent 将EGL 渲染上下文绑定到当前渲染线程。


    在 OpenGL ES 中使用 SDL

    这可以通过调用 SDL_GetWMInfo() 来获得所需的句柄来完成,例如:

    SDL_SysWMinfo sysWmInfo;
    SDL_VERSION(&sysWmInfo.version);
    SDL_GetWMInfo(&sysWmInfo);
    eglDisplay = eglGetDisplay((EGLNativeDisplayType)sysWmInfo.info.x11.display);
    ...
    eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)sysWmInfo.info.x11.window, NULL);
    

    或者,

    您尝试使用SDL_GL_MakeCurrent 吗?

    【讨论】:

    • 我使用 SDL 创建了我的上下文。然后我如何继续使用 EGL 创建另一个上下文?
    • 使用 SDL 创建上下文后,你有一些处理程序吗?如果是这样,我会尝试在不同的线程上将此处理程序与 SDL_GL_MakeCurrent 一起使用。 (SDL_Window* 和 SDL_GLContext,你应该让它们都调用 SDL_GL_MakeCurrent)
    • 感谢您为我指明正确的方向。我已经编辑了我的问题以包括我创建的 OpenGL ES 上下文。我可以在第一个线程中调用 SDL_GL_MakeCurrent 的通用函数中使用处理程序吗?
    • 我不确定它在 SDL 中是如何工作的,但我会尝试使用您在第一个线程中创建的窗口和上下文从另一个线程调用 SDL_GL_MakeCurrent。
    • 如果在另一个线程上调用 SDL_GL_MakeCurrent 并传递您在第一个线程上获得的参数(窗口、上下文)确实有效,请注意多线程。通过在每个循环开始时调用 SDL_GL_MakeCurrent,第一个线程上的绘图循环很有可能与另一个线程上的绘图循环发生冲突。你应该同步它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多