Fixed bug 3901 - Fix vsync-ed pageflips on the KMSDRM video driver
authorSam Lantinga <slouken@libsdl.org>
Sat, 21 Oct 2017 04:20:57 -0700
changeset 11643273acc67dbfa
parent 11642 e081e63addd3
child 11644 05ff2be7e0d5
Fixed bug 3901 - Fix vsync-ed pageflips on the KMSDRM video driver

Manuel

I noticed that, at least on Intel GPU hardware, passing SDL_RENDERER_PRESENTVSYNC would result on a static console instead of the program graphics.
That was due to the fact that calling drmModePageFlip() only works if we have previously set up CRTC to one of the GBM buffers with a drmModeSetCrtc() call, so now it's done and things work as expected.

The KMSDRM_GLES_SetupCrtc() call is done only one time, only when needed (when egl_swapinterval is not 0: when it's 0, there's no need for it because we flip by calling drmModePageFlip() anyway).
The place where KMSDRM_GLES_SetupCrtc() call is done may look strange, but it's right: it needs EGL completely ready because it needs to call eglSwapBuffers() internally to work (see more comments about it in the code).
src/video/kmsdrm/SDL_kmsdrmopengles.c
src/video/kmsdrm/SDL_kmsdrmvideo.c
src/video/kmsdrm/SDL_kmsdrmvideo.h
     1.1 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.c	Fri Oct 20 16:53:42 2017 -0700
     1.2 +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c	Sat Oct 21 04:20:57 2017 -0700
     1.3 @@ -42,6 +42,40 @@
     1.4  
     1.5  SDL_EGL_CreateContext_impl(KMSDRM)
     1.6  
     1.7 +SDL_bool
     1.8 +KMSDRM_GLES_SetupCrtc(_THIS, SDL_Window * window) {
     1.9 +    SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
    1.10 +    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    1.11 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
    1.12 +    KMSDRM_FBInfo *fb_info;
    1.13 +
    1.14 +    if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
    1.15 +	SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed on CRTC setup");
    1.16 +	return SDL_FALSE;
    1.17 +    }
    1.18 +
    1.19 +    wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
    1.20 +    if (wdata->next_bo == NULL) {
    1.21 +	SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer on CRTC setup");
    1.22 +	return SDL_FALSE;
    1.23 +    }
    1.24 +
    1.25 +    fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
    1.26 +    if (fb_info == NULL) {
    1.27 +	return SDL_FALSE;
    1.28 +    }
    1.29 +
    1.30 +    if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
    1.31 +			    0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode) != 0) {
    1.32 +       SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC to a GBM buffer");
    1.33 +       return SDL_FALSE;
    1.34 +
    1.35 +    }
    1.36 +    
    1.37 +    wdata->crtc_ready = SDL_TRUE;
    1.38 +    return SDL_TRUE;
    1.39 +}
    1.40 +
    1.41  int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
    1.42      if (!_this->egl_data) {
    1.43          return SDL_SetError("EGL not initialized");
    1.44 @@ -118,6 +152,16 @@
    1.45          }
    1.46      } else {
    1.47          /* Queue page flip at vsync */
    1.48 +
    1.49 +	/* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
    1.50 +           or FlipPage won't work in some cases. */
    1.51 +	if (!wdata->crtc_ready) {
    1.52 +            if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
    1.53 +                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
    1.54 +                return 0;
    1.55 +            } 
    1.56 +	}
    1.57 +
    1.58          /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
    1.59              vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
    1.60          ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
     2.1 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c	Fri Oct 20 16:53:42 2017 -0700
     2.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c	Sat Oct 21 04:20:57 2017 -0700
     2.3 @@ -522,6 +522,12 @@
     2.4      }
     2.5  #endif /* SDL_VIDEO_OPENGL_EGL */
     2.6  
     2.7 +    /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want
     2.8 +       drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
     2.9 +       need to do eglSwapBuffers so we can get a valid GBM buffer object to call 
    2.10 +       drmModeSetCrtc on it. */
    2.11 +    wdata->crtc_ready = SDL_FALSE;    
    2.12 +
    2.13      /* Setup driver data for this window */
    2.14      window->driverdata = wdata;
    2.15  
     3.1 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h	Fri Oct 20 16:53:42 2017 -0700
     3.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h	Sat Oct 21 04:20:57 2017 -0700
     3.3 @@ -62,6 +62,7 @@
     3.4      struct gbm_bo *current_bo;
     3.5      struct gbm_bo *next_bo;
     3.6      SDL_bool waiting_for_flip;
     3.7 +    SDL_bool crtc_ready;
     3.8  #if SDL_VIDEO_OPENGL_EGL
     3.9      EGLSurface egl_surface;
    3.10  #endif