Mac and Linux SDL2 binary snapshots
Edward Rudd
2020-05-02 03f8528315fa46c95991a34f3325d7b33ae5538c
source/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -1,6 +1,6 @@
/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
@@ -37,44 +37,11 @@
int
KMSDRM_GLES_LoadLibrary(_THIS, const char *path) {
    return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA);
    NativeDisplayType display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm;
    return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA);
}
SDL_EGL_CreateContext_impl(KMSDRM)
SDL_bool
KMSDRM_GLES_SetupCrtc(_THIS, SDL_Window * window) {
    SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    KMSDRM_FBInfo *fb_info;
    if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed on CRTC setup");
        return SDL_FALSE;
    }
    wdata->crtc_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
    if (wdata->crtc_bo == NULL) {
        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer on CRTC setup");
        return SDL_FALSE;
    }
    fb_info = KMSDRM_FBFromBO(_this, wdata->crtc_bo);
    if (fb_info == NULL) {
        return SDL_FALSE;
    }
    if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
                            0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode) != 0) {
       SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC to a GBM buffer");
       return SDL_FALSE;
    }
    wdata->crtc_ready = SDL_TRUE;
    return SDL_TRUE;
}
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
    if (!_this->egl_data) {
@@ -92,90 +59,86 @@
int
KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
    SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
    SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
    KMSDRM_FBInfo *fb_info;
    int ret;
    int ret, timeout;
    /* Do we still need to wait for a flip? */
    int timeout = 0;
    /* Recreate the GBM / EGL surfaces if the display mode has changed */
    if (windata->egl_surface_dirty) {
        KMSDRM_CreateSurfaces(_this, window);
    }
    /* Wait for confirmation that the next front buffer has been flipped, at which
       point the previous front buffer can be released */
    timeout = 0;
    if (_this->egl_data->egl_swapinterval == 1) {
        timeout = -1;
    }
    if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) {
    if (!KMSDRM_WaitPageFlip(_this, windata, timeout)) {
        return 0;
    }
    /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
    if (wdata->next_bo != NULL) {
        KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->current_bo);
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->next_bo); */
        wdata->current_bo = wdata->next_bo;
        wdata->next_bo = NULL;
    /* Release the previous front buffer */
    if (windata->curr_bo) {
        KMSDRM_gbm_surface_release_buffer(windata->gs, windata->curr_bo);
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)windata->curr_bo); */
        windata->curr_bo = NULL;
    }
    if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
    windata->curr_bo = windata->next_bo;
    /* Make the current back buffer the next front buffer */
    if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface))) {
        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
        return 0;
    }
    if (wdata->current_bo == NULL) {
        wdata->current_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
        if (wdata->current_bo == NULL) {
            return 0;
        }
    }
    wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
    if (wdata->next_bo == NULL) {
    /* Lock the next front buffer so it can't be allocated as a back buffer */
    windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
    if (!windata->next_bo) {
        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
        return 0;
    /* } else {
        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->next_bo); */
        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)windata->next_bo); */
    }
    fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
    if (fb_info == NULL) {
    fb_info = KMSDRM_FBFromBO(_this, windata->next_bo);
    if (!fb_info) {
        return 0;
    }
    if (_this->egl_data->egl_swapinterval == 0) {
        /* Swap buffers instantly, possible tearing */
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
            displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
        ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
                                    0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
        if(ret != 0) {
            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
    if (!windata->curr_bo) {
        /* On the first swap, immediately present the new front buffer. Before
           drmModePageFlip can be used the CRTC has to be configured to use
           the current connector and mode with drmModeSetCrtc */
        ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
                                    0, &dispdata->conn->connector_id, 1, &dispdata->mode);
        if (ret) {
          SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC");
        }
    } else {
        /* Queue page flip at vsync */
        /* On subsequent swaps, queue the new front buffer to be flipped during
           the next vertical blank */
        ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id,
                                     DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip)",
            viddata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
        /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
           or FlipPage won't work in some cases. */
        if (!wdata->crtc_ready) {
            if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
                return 0;
        if (_this->egl_data->egl_swapinterval == 1) {
            if (ret == 0) {
                windata->waiting_for_flip = SDL_TRUE;
            } else {
                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
            }
        }
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
        ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
                                     DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
        if (ret == 0) {
            wdata->waiting_for_flip = SDL_TRUE;
        } else {
            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
        }
        /* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
           Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>" to enable this. */
        if (wdata->double_buffer) {
            KMSDRM_WaitPageFlip(_this, wdata, -1);
        if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
            KMSDRM_WaitPageFlip(_this, windata, -1);
        }
    }