kmsdrm: move videomode restoration on VideoQuit() to using the atomic interface instead of the legacy drmModeSetCrtc() function. Refactoring of get_plane_id().

This commit is contained in:
Manuel Alfayate Corchete 2020-08-05 18:55:22 +02:00
parent fc722b2d21
commit 09692b6170
3 changed files with 54 additions and 40 deletions

View File

@ -80,15 +80,16 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb; KMSDRM_FBInfo *fb;
int ret; int ret;
uint32_t flags = 0;
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; /* Do we need to set video mode this time? If yes, pass the right flag and issue a blocking atomic ioctl. */
if (dispdata->modeset_pending) {
/* Do we need to set video mode this time? */
if (windata->crtc_setup_pending) {
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
windata->crtc_setup_pending = SDL_FALSE; dispdata->modeset_pending = SDL_FALSE;
}
else {
flags |= DRM_MODE_ATOMIC_NONBLOCK;
} }
/*************************************************************************/ /*************************************************************************/
/* Block for telling KMS to wait for GPU rendering of the current frame */ /* Block for telling KMS to wait for GPU rendering of the current frame */
@ -184,12 +185,15 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb; KMSDRM_FBInfo *fb;
int ret; int ret;
uint32_t flags = 0;
/* Do we need to set video mode this time? */ /* Do we need to set video mode this time? If yes, pass the right flag and issue a blocking atomic ioctl. */
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; if (dispdata->modeset_pending) {
if (windata->crtc_setup_pending) {
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
windata->crtc_setup_pending = SDL_FALSE; dispdata->modeset_pending = SDL_FALSE;
}
else {
flags |= DRM_MODE_ATOMIC_NONBLOCK;
} }
/* Create the fence that will be inserted in the cmdstream exactly at the end /* Create the fence that will be inserted in the cmdstream exactly at the end

View File

@ -333,18 +333,27 @@ void get_planes_info(_THIS)
#endif #endif
/* Get a plane that is PRIMARY (there's no guarantee that we have overlays in all hardware!) /* Get a plane that is PRIMARY (there's no guarantee that we have overlays in all hardware,
and can use the CRTC we have chosen. That's all. */ so we can really only count on having one primary plane) and can use the CRTC we have chosen. */
uint32_t get_plane_id(_THIS) uint32_t get_plane_id(_THIS, drmModeRes *resources)
{ {
drmModePlaneResPtr plane_resources; drmModePlaneResPtr plane_resources;
uint32_t i, j; uint32_t i, j;
uint32_t crtc_index = 0;
int ret = -EINVAL; int ret = -EINVAL;
int found_primary = 0; int found_primary = 0;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
/* Get the crtc_index for the current CRTC. Needed to find out if a plane supports the CRTC. */
for (i = 0; i < resources->count_crtcs; i++) {
if (resources->crtcs[i] == dispdata->crtc_id) {
crtc_index = i;
break;
}
}
plane_resources = KMSDRM_drmModeGetPlaneResources(viddata->drm_fd); plane_resources = KMSDRM_drmModeGetPlaneResources(viddata->drm_fd);
if (!plane_resources) { if (!plane_resources) {
printf("drmModeGetPlaneResources failed: %s\n", strerror(errno)); printf("drmModeGetPlaneResources failed: %s\n", strerror(errno));
@ -363,9 +372,10 @@ uint32_t get_plane_id(_THIS)
} }
/* See if the current CRTC is available for this plane. */ /* See if the current CRTC is available for this plane. */
if (plane->possible_crtcs & (1 << dispdata->crtc_index)) { if (plane->possible_crtcs & (1 << crtc_index)) {
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd, plane_id, DRM_MODE_OBJECT_PLANE); drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd,
plane_id, DRM_MODE_OBJECT_PLANE);
ret = plane_id; ret = plane_id;
/* Search the plane props, to see if it's a primary plane. */ /* Search the plane props, to see if it's a primary plane. */
@ -717,7 +727,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
/* We take note here about the need to do a modeset in the atomic_commit(), /* We take note here about the need to do a modeset in the atomic_commit(),
called in KMSDRM_GLES_SwapWindow(). */ called in KMSDRM_GLES_SwapWindow(). */
windata->crtc_setup_pending = SDL_TRUE; dispdata->modeset_pending = SDL_TRUE;
return 0; return 0;
} }
@ -870,20 +880,12 @@ KMSDRM_VideoInit(_THIS)
/* Atomic block */ /* Atomic block */
/****************/ /****************/
/* Find crtc_index. It's used to find out if a plane supports a CRTC. */
/* TODO: include this in the get_plane_id() function somehow. */
for (int i = 0; i < resources->count_crtcs; i++) {
if (resources->crtcs[i] == dispdata->crtc_id) {
dispdata->crtc_index = i;
break;
}
}
/* Initialize the fences and their fds: */ /* Initialize the fences and their fds: */
dispdata->kms_fence = NULL; dispdata->kms_fence = NULL;
dispdata->gpu_fence = NULL; dispdata->gpu_fence = NULL;
dispdata->kms_out_fence_fd = -1, dispdata->kms_out_fence_fd = -1,
dispdata->kms_in_fence_fd = -1, dispdata->kms_in_fence_fd = -1,
dispdata->modeset_pending = SDL_FALSE;
/*********************/ /*********************/
/* Atomic block ends */ /* Atomic block ends */
@ -949,7 +951,7 @@ KMSDRM_VideoInit(_THIS)
goto cleanup; goto cleanup;
} }
dispdata->plane_id = get_plane_id(_this); dispdata->plane_id = get_plane_id(_this, resources);
if (!dispdata->plane_id) { if (!dispdata->plane_id) {
ret = SDL_SetError("could not find a suitable plane."); ret = SDL_SetError("could not find a suitable plane.");
goto cleanup; goto cleanup;
@ -1011,6 +1013,11 @@ KMSDRM_VideoInit(_THIS)
SDL_EVDEV_Init(); SDL_EVDEV_Init();
#endif #endif
if (encoder)
KMSDRM_drmModeFreeEncoder(encoder);
if (resources)
KMSDRM_drmModeFreeResources(resources);
KMSDRM_InitMouse(_this); KMSDRM_InitMouse(_this);
return ret; return ret;
@ -1044,12 +1051,21 @@ cleanup:
return ret; return ret;
} }
/* Fn to restore original video mode and crtc buffer on quit, using the atomic interface. */
/*int
restore_video (_THIS)
{
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
ret = drm_atomic_commit(_this, fb->fb_id, flags);
}*/
void void
KMSDRM_VideoQuit(_THIS) KMSDRM_VideoQuit(_THIS)
{ {
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()"); SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
if (_this->gl_config.driver_loaded) { if (_this->gl_config.driver_loaded) {
@ -1062,16 +1078,14 @@ KMSDRM_VideoQuit(_THIS)
viddata->max_windows = 0; viddata->max_windows = 0;
viddata->num_windows = 0; viddata->num_windows = 0;
/* Restore saved CRTC settings */ /* Restore original videomode. */
if (viddata->drm_fd >= 0 && dispdata && dispdata->connector && dispdata->crtc) { if (viddata->drm_fd >= 0 && dispdata && dispdata->connector && dispdata->crtc) {
drmModeConnector *conn = dispdata->connector; uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
drmModeCrtc *crtc = dispdata->crtc;
int ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, crtc->crtc_id, crtc->buffer_id, int ret = drm_atomic_commit(_this, dispdata->crtc->buffer_id, flags);
crtc->x, crtc->y, &conn->connector_id, 1, &crtc->mode);
if (ret != 0) { if (ret != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode"); SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original videomode");
} }
} }
/****************/ /****************/
@ -1191,11 +1205,9 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
goto error; goto error;
} }
/* Init windata fields. */ /* Init fields. */
windata->crtc_setup_pending = SDL_FALSE;
windata->egl_surface_dirty = SDL_FALSE; windata->egl_surface_dirty = SDL_FALSE;
/* First remember that certain functions in SDL_Video.c will call *_SetDisplayMode when the /* First remember that certain functions in SDL_Video.c will call *_SetDisplayMode when the
SDL_WINDOW_FULLSCREEN is set and SDL_WINDOW_FULLSCREEN_DESKTOP is not set. SDL_WINDOW_FULLSCREEN is set and SDL_WINDOW_FULLSCREEN_DESKTOP is not set.
So I am determining here that the behavior when creating an SDL_Window() in KMSDRM, is: So I am determining here that the behavior when creating an SDL_Window() in KMSDRM, is:

View File

@ -75,14 +75,13 @@ typedef struct SDL_DisplayData
drmModeObjectProperties *connector_props; drmModeObjectProperties *connector_props;
drmModePropertyRes **connector_props_info; drmModePropertyRes **connector_props_info;
int crtc_index;
int kms_in_fence_fd; int kms_in_fence_fd;
int kms_out_fence_fd; int kms_out_fence_fd;
EGLSyncKHR kms_fence; /* Signaled when kms completes changes requested in atomic iotcl (pageflip, etc). */ EGLSyncKHR kms_fence; /* Signaled when kms completes changes requested in atomic iotcl (pageflip, etc). */
EGLSyncKHR gpu_fence; /* Signaled when GPU rendering is done. */ EGLSyncKHR gpu_fence; /* Signaled when GPU rendering is done. */
SDL_bool modeset_pending;
} SDL_DisplayData; } SDL_DisplayData;
@ -93,7 +92,6 @@ typedef struct SDL_WindowData
struct gbm_bo *bo; struct gbm_bo *bo;
struct gbm_bo *next_bo; struct gbm_bo *next_bo;
struct gbm_bo *crtc_bo; struct gbm_bo *crtc_bo;
SDL_bool crtc_setup_pending;
#if SDL_VIDEO_OPENGL_EGL #if SDL_VIDEO_OPENGL_EGL
SDL_bool egl_surface_dirty; SDL_bool egl_surface_dirty;
EGLSurface egl_surface; EGLSurface egl_surface;