Почему eglCreatePbufferSurface дает EGL_NO_SURFACE, когда установлена ​​переменная среды DISPLAY?

Я столкнулся с очень странной проблемой. Я использую Убунту 20.04. В следующем минимальном примере предполагается настроить контекст EGL (для последующего рендеринга OpenGL).

#include <EGL/egl.h>
#include <stdexcept>
#include <sstream>

#define ASSERT( expression ) \
    if( !( expression ) ) \
    { \
        std::stringstream details; \
        details \
            << "Failed expression: " << #expression << std::endl \
            << "File: " << __FILE__ << std::endl \
            << "Line: " << __LINE__; \
        throw std::runtime_error( details.str() ); \
    }

static const EGLint CONFIG_ATTRIBS[] =
{
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    EGL_BLUE_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_DEPTH_SIZE, 8,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
    EGL_NONE
};

static const EGLint PBUFFER_ATTRIBS[] =
{
    EGL_WIDTH, 8,
    EGL_HEIGHT, 8,
    EGL_NONE
};

int main()
{
    EGLDisplay eglDpy;
    EGLSurface eglSurf;
    EGLContext eglCtx;
    
    eglDpy = eglGetDisplay( EGL_DEFAULT_DISPLAY );
    EGLint major, minor;
    eglInitialize( eglDpy, &major, &minor );
    
    eglBindAPI( EGL_OPENGL_API );

    EGLint numConfigs;
    EGLConfig eglCfg;

    auto cfgResult = eglChooseConfig( eglDpy, CONFIG_ATTRIBS, &eglCfg, 1, &numConfigs );
    ASSERT( cfgResult == EGL_TRUE );

    eglSurf = eglCreatePbufferSurface( eglDpy, eglCfg, PBUFFER_ATTRIBS );
    ASSERT( eglSurf != EGL_NO_SURFACE ); // <-- this assertion fails

    eglCtx  = eglCreateContext( eglDpy, eglCfg, EGL_NO_CONTEXT, NULL );
    ASSERT( eglCtx != EGL_NO_CONTEXT );
}

Я использую командную строку c++ egltest.cpp -lGL -lEGL -o egltest для компиляции и компоновки. Когда я нахожусь на рабочем столе и после этого запускаю ./egltest, возникает следующая ошибка:

terminate called after throwing an instance of 'std::runtime_error'
  what():  Failed expression: eglSurf != EGL_NO_SURFACE
File: egltest.cpp
Line: 53

Однако это работает, если я использую unset DISPLAY && ./egltest для запуска. Таким образом, обходным путем было бы использовать unsetenv( "DISPLAY" ); в первой строке моей функции main (проверено и да, это тоже работает). Но, и это большое но, почему необходимо сбрасывать DISPLAY?


person theV0ID    schedule 08.06.2021    source источник
comment
Убедитесь, что eglChooseConfig() возвращает что-то большее нуля для numConfigs перед попыткой eglCreatePbufferSurface().   -  person genpfault    schedule 08.06.2021
comment
@genpfault Возвращаемое значение eglChooseConfig всегда равно 1, независимо от того, отключил ли я DISPLAY или нет. Однако, согласно документам, return значение 1 указывает на успех, а 0 указывает на неудачу, поэтому eglChooseConfig в порядке. Я обновил вопрос, чтобы отразить это.   -  person theV0ID    schedule 08.06.2021
comment
Не фактическое возвращаемое значение, а выходной аргумент num_config. Он может вернуть успех, но все же установить num_config на ноль (и не обновить configs), если ни одна конфигурация не соответствует attrib_list.   -  person genpfault    schedule 08.06.2021
comment
@genpfault Вы были правы, num_config устанавливается равным нулю, если установлена ​​переменная среды DISPLAY. В противном случае устанавливается значение 1. Но почему?   -  person theV0ID    schedule 08.06.2021
comment
Можете попробовать перепроверить атрибуты, которые вы пытаетесь использовать, с дампом атрибутов per-EGLDisplay, предоставленным eglinfo (из mesa-utils-extra в Debian).   -  person genpfault    schedule 08.06.2021
comment
В моей системе eglGetDisplay(EGL_DEFAULT_DISPLAY), похоже, используется платформа GBM, в которой нет конфигураций pbuffer. Принудительное использование X11 через eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, EGL_DEFAULT_DISPLAY, nullptr) показывает некоторые конфигурации pbuffer, соответствующие eglinfo. (Обратите внимание, что EGL_PLATFORM_X11_KHR — это перечисление расширений и соответствующее расширение (KHR_platform_x11) следует проверить на наличие поддержки во время выполнения, прежде чем использовать его)   -  person genpfault    schedule 08.06.2021