Запуск приложения SDL / OpenGLES на определенном дисплее в XServer - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь перенести приложение на встроенную систему, которую пытаюсь создать.Встроенная система основана на Raspberry Pi Zero W и использует пользовательскую сборку Yocto.

Приложение для переноса написано с использованием SDL / OpenGLES, насколько я понимаю.Мне трудно понять, как установить соединение, подобное приведенному ниже:

SDL APP -----> XServer ($DISPLAY) -------> Framebuffer /dev/fb1 ($FRAMEBUFFER)

Система имеет два дисплея: один HDMI на /dev/fb0 и один TFT на /dev/fb1.Я пытаюсь запустить приложение SDL на TFT.Ниже приведены шаги, которые я делаю:

Первый , запустите XServer на DISPLAY=:1, который подключен к /dev/fb1:

FRAMEBUFFER=/dev/fb1 xinit /etc/X11/Xsession -- /usr/bin/Xorg :1 -br -pn -nolisten tcp -dpi 100

Первый шаг кажетсякак будто это работает.Я вижу загрузку LXDE на моем TFT-экране.Проверяя дисплей, я получаю правильное разрешение экрана:

~/projects# DISPLAY=:1 xrandr -q
xrandr: Failed to get size of gamma for output default
Screen 0: minimum 320 x 240, current 320 x 240, maximum 320 x 240
default connected 320x240+0+0 0mm x 0mm
   320x240        0.00* 

Second , я хотел бы запустить приложение, написанное на SDL, используя x11.Я думаю, что должно работать при просмотре приложения на TFT.Для этого я стараюсь:

SDL_VIDEODRIVER=x11 SDL_WINDOWID=1 DISPLAY=:1 ./SDL_App

Независимо от того, какой номер дисплея я выберу, он запускается на моем дисплее HDMI, а не на TFT.Так что теперь я думаю, что человек, который написал приложение, жестко закодировало что-то в коде приложения:

void init_ogl(void)
{
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_DISPMANX_ALPHA_T alpha;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] =
    {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    EGLConfig config;

    // Get an EGL display connection
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(display!=EGL_NO_DISPLAY);

    // Initialize the EGL display connection
    result = eglInitialize(display, NULL, NULL);
    assert(EGL_FALSE != result);

    // Get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // Create an EGL rendering context
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
    assert(context!=EGL_NO_CONTEXT);

    // Create an EGL window surface
    success = graphics_get_display_size( 0 /* LCD */  , &screen_width, &screen_height);
    printf ("Screen width= %d\n", screen_width);
    printf ("Screen height= %d\n", screen_height);
    assert( success >= 0 );

    int32_t zoom = screen_width / GAMEBOY_WIDTH;
    int32_t zoom2 = screen_height / GAMEBOY_HEIGHT;

    if (zoom2 < zoom)
        zoom = zoom2;

    int32_t display_width = GAMEBOY_WIDTH * zoom;
    int32_t display_height = GAMEBOY_HEIGHT * zoom;
    int32_t display_offset_x = (screen_width / 2) - (display_width / 2);
    int32_t display_offset_y = (screen_height / 2) - (display_height / 2);

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = screen_width;
    dst_rect.height = screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = screen_width << 16;
    src_rect.height = screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */ );
    dispman_update = vc_dispmanx_update_start( 0 );

    alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
    alpha.opacity = 255;
    alpha.mask = 0;

    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
        0/*layer*/, &dst_rect, 0/*src*/,
        &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, DISPMANX_NO_ROTATE/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = screen_width;
    nativewindow.height = screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    surface = eglCreateWindowSurface( display, config, &nativewindow, NULL );
    assert(surface != EGL_NO_SURFACE);

    // Connect the context to the surface
    result = eglMakeCurrent(display, surface, surface, context);
    assert(EGL_FALSE != result);

    eglSwapInterval(display, 1);

    glGenTextures(1, &theGBTexture);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, theGBTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0.0f, screen_width, screen_height, 0.0f, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glViewport(0.0f, 0.0f, screen_width, screen_height);

    quadVerts[0] = display_offset_x;
    quadVerts[1] = display_offset_y;
    quadVerts[2] = display_offset_x + display_width;
    quadVerts[3] = display_offset_y;
    quadVerts[4] = display_offset_x + display_width;
    quadVerts[5] = display_offset_y + display_height;
    quadVerts[6] = display_offset_x;
    quadVerts[7] = display_offset_y + display_height;

    glVertexPointer(2, GL_SHORT, 0, quadVerts);
    glEnableClientState(GL_VERTEX_ARRAY);

    glTexCoordPointer(2, GL_FLOAT, 0, kQuadTex);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glClear(GL_COLOR_BUFFER_BIT);
}

void init_sdl(void)
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
    {
        Log("SDL Error Init: %s", SDL_GetError());
    }

    theWindow = SDL_CreateWindow("Gearboy", 0, 0, 0, 0, 0);

    if (theWindow == NULL)
    {
        Log("SDL Error Video: %s", SDL_GetError());
    }
    ...

}

На первый взгляд, я обнаружил две строки: vc_dispmanx_display_open( 0 /* LCD */ ); и graphics_get_display_size( 0 /* LCD */ , &screen_width, &screen_height);.Я попытался изменить параметр дисплея на 1, думая, что он ссылается на DISPLAY=:1, но ничего не сделал.Я добавил журналы для разрешения экрана, и я получил 1920x1080, что является разрешением дисплея HDMI.Я думаю, что должно быть что-то с той частью кода EGL, которую я пропускаю.Что мне делать прямо сейчас?Достаточно ли честна моя логика или я что-то упустил?

Любые требования, пожалуйста, дайте мне знать.Любое руководство по этой проблеме высоко ценится.

РЕДАКТИРОВАТЬ: Я видел, что некоторые люди используют следующее, но raspberry pi zero не может найти EGL / eglvivante.h для функций fb, поэтому яневозможно скомпилировать:

int fbnum = 1; // fbnum is an integer for /dev/fb1 fbnum = 1
EGLNativeDisplayType native_display = fbGetDisplayByIndex(fbnum);
EGLNativeWindowType native_window = fbCreateWindow(native_display, 0, 0, 0, 0);
display = eglGetDisplay(native_display);
...