kmsdrm: move videomode restoration on VideoQuit() to using the atomic interface instead of the legacy drmModeSetCrtc() function. Refactoring of get_plane_id().
authorManuel Alfayate Corchete
Wed, 05 Aug 2020 18:55:22 +0200
changeset 139779b0de62c344b
parent 13976 4f06c06b6d19
child 13978 fdb9d9e9f168
kmsdrm: move videomode restoration on VideoQuit() to using the atomic interface instead of the legacy drmModeSetCrtc() function. Refactoring of get_plane_id().
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	Wed Aug 05 15:28:51 2020 +0200
     1.2 +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c	Wed Aug 05 18:55:22 2020 +0200
     1.3 @@ -80,15 +80,16 @@
     1.4      SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
     1.5      KMSDRM_FBInfo *fb;
     1.6      int ret;
     1.7 -
     1.8 -    uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
     1.9 +    uint32_t flags = 0;
    1.10  
    1.11 -    /* Do we need to set video mode this time? */
    1.12 -    if (windata->crtc_setup_pending) {
    1.13 +    /* Do we need to set video mode this time? If yes, pass the right flag and issue a blocking atomic ioctl. */
    1.14 +    if (dispdata->modeset_pending) {
    1.15          flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
    1.16 -        windata->crtc_setup_pending = SDL_FALSE;
    1.17 +        dispdata->modeset_pending = SDL_FALSE;
    1.18      }
    1.19 -
    1.20 +    else {
    1.21 +        flags |= DRM_MODE_ATOMIC_NONBLOCK;
    1.22 +    }
    1.23  
    1.24      /*************************************************************************/
    1.25      /* Block for telling KMS to wait for GPU rendering of the current frame  */
    1.26 @@ -184,12 +185,15 @@
    1.27      SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
    1.28      KMSDRM_FBInfo *fb;
    1.29      int ret;
    1.30 +    uint32_t flags = 0;
    1.31  
    1.32 -    /* Do we need to set video mode this time? */
    1.33 -    uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
    1.34 -    if (windata->crtc_setup_pending) {
    1.35 +    /* Do we need to set video mode this time? If yes, pass the right flag and issue a blocking atomic ioctl. */
    1.36 +    if (dispdata->modeset_pending) {
    1.37          flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
    1.38 -        windata->crtc_setup_pending = SDL_FALSE;
    1.39 +        dispdata->modeset_pending = SDL_FALSE;
    1.40 +    }
    1.41 +    else {
    1.42 +        flags |= DRM_MODE_ATOMIC_NONBLOCK;
    1.43      }
    1.44  
    1.45      /* Create the fence that will be inserted in the cmdstream exactly at the end
     2.1 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c	Wed Aug 05 15:28:51 2020 +0200
     2.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c	Wed Aug 05 18:55:22 2020 +0200
     2.3 @@ -333,18 +333,27 @@
     2.4  
     2.5  #endif
     2.6  
     2.7 -/* Get a plane that is PRIMARY (there's no guarantee that we have overlays in all hardware!)
     2.8 -   and can use the CRTC we have chosen. That's all. */ 
     2.9 -uint32_t get_plane_id(_THIS)
    2.10 +/* Get a plane that is PRIMARY (there's no guarantee that we have overlays in all hardware,
    2.11 +   so we can really only count on having one primary plane) and can use the CRTC we have chosen. */ 
    2.12 +uint32_t get_plane_id(_THIS, drmModeRes *resources)
    2.13  {
    2.14      drmModePlaneResPtr plane_resources;
    2.15      uint32_t i, j;
    2.16 +    uint32_t crtc_index = 0;
    2.17      int ret = -EINVAL;
    2.18      int found_primary = 0;
    2.19  
    2.20      SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
    2.21      SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
    2.22  
    2.23 +    /* Get the crtc_index for the current CRTC. Needed to find out if a plane supports the CRTC. */
    2.24 +    for (i = 0; i < resources->count_crtcs; i++) {
    2.25 +	if (resources->crtcs[i] == dispdata->crtc_id) {
    2.26 +	    crtc_index = i;
    2.27 +	    break;
    2.28 +	}
    2.29 +    }
    2.30 +
    2.31      plane_resources = KMSDRM_drmModeGetPlaneResources(viddata->drm_fd);
    2.32      if (!plane_resources) {
    2.33  	printf("drmModeGetPlaneResources failed: %s\n", strerror(errno));
    2.34 @@ -363,9 +372,10 @@
    2.35  	}
    2.36  
    2.37          /* See if the current CRTC is available for this plane. */
    2.38 -	if (plane->possible_crtcs & (1 << dispdata->crtc_index)) {
    2.39 +	if (plane->possible_crtcs & (1 << crtc_index)) {
    2.40  
    2.41 -	    drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
    2.42 +	    drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd,
    2.43 +                                                   plane_id, DRM_MODE_OBJECT_PLANE);
    2.44  	    ret = plane_id;
    2.45  
    2.46              /* Search the plane props, to see if it's a primary plane. */
    2.47 @@ -379,7 +389,7 @@
    2.48  		    found_primary = 1;
    2.49  		}
    2.50  
    2.51 -		KMSDRM_drmModeFreeProperty(p);
    2.52 +                KMSDRM_drmModeFreeProperty(p);
    2.53  	    }
    2.54  
    2.55  	    KMSDRM_drmModeFreeObjectProperties(props);
    2.56 @@ -717,7 +727,7 @@
    2.57  
    2.58      /* We take note here about the need to do a modeset in the atomic_commit(),
    2.59         called in KMSDRM_GLES_SwapWindow(). */
    2.60 -    windata->crtc_setup_pending = SDL_TRUE;
    2.61 +    dispdata->modeset_pending = SDL_TRUE;
    2.62  
    2.63      return 0;
    2.64  }
    2.65 @@ -870,20 +880,12 @@
    2.66      /* Atomic block */
    2.67      /****************/
    2.68  
    2.69 -    /* Find crtc_index. It's used to find out if a plane supports a CRTC. */
    2.70 -    /* TODO: include this in the get_plane_id() function somehow. */
    2.71 -    for (int i = 0; i < resources->count_crtcs; i++) {
    2.72 -	if (resources->crtcs[i] == dispdata->crtc_id) {
    2.73 -	    dispdata->crtc_index = i;
    2.74 -	    break;
    2.75 -	}
    2.76 -    }
    2.77 -
    2.78      /* Initialize the fences and their fds: */
    2.79      dispdata->kms_fence = NULL;
    2.80      dispdata->gpu_fence = NULL;
    2.81      dispdata->kms_out_fence_fd = -1,
    2.82      dispdata->kms_in_fence_fd  = -1,
    2.83 +    dispdata->modeset_pending  = SDL_FALSE;
    2.84  
    2.85      /*********************/
    2.86      /* Atomic block ends */
    2.87 @@ -949,7 +951,7 @@
    2.88          goto cleanup;
    2.89      }
    2.90  
    2.91 -    dispdata->plane_id = get_plane_id(_this);
    2.92 +    dispdata->plane_id = get_plane_id(_this, resources);
    2.93      if (!dispdata->plane_id) {
    2.94          ret = SDL_SetError("could not find a suitable plane.");
    2.95          goto cleanup;
    2.96 @@ -1011,6 +1013,11 @@
    2.97      SDL_EVDEV_Init();
    2.98  #endif
    2.99  
   2.100 +    if (encoder)
   2.101 +        KMSDRM_drmModeFreeEncoder(encoder);
   2.102 +    if (resources)
   2.103 +        KMSDRM_drmModeFreeResources(resources);
   2.104 +
   2.105      KMSDRM_InitMouse(_this);
   2.106  
   2.107      return ret;
   2.108 @@ -1044,12 +1051,21 @@
   2.109      return ret;
   2.110  }
   2.111  
   2.112 +/* Fn to restore original video mode and crtc buffer on quit, using the atomic interface. */
   2.113 +/*int
   2.114 +restore_video (_THIS)
   2.115 +{
   2.116 +    SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
   2.117 +
   2.118 +    ret = drm_atomic_commit(_this, fb->fb_id, flags);
   2.119 +
   2.120 +}*/
   2.121 +
   2.122  void
   2.123  KMSDRM_VideoQuit(_THIS)
   2.124  {
   2.125      SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
   2.126      SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
   2.127 -
   2.128      SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
   2.129  
   2.130      if (_this->gl_config.driver_loaded) {
   2.131 @@ -1062,16 +1078,14 @@
   2.132      viddata->max_windows = 0;
   2.133      viddata->num_windows = 0;
   2.134  
   2.135 -    /* Restore saved CRTC settings */
   2.136 +    /* Restore original videomode. */
   2.137      if (viddata->drm_fd >= 0 && dispdata && dispdata->connector && dispdata->crtc) {
   2.138 -        drmModeConnector *conn = dispdata->connector;
   2.139 -        drmModeCrtc *crtc = dispdata->crtc;
   2.140 +        uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
   2.141  
   2.142 -        int ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, crtc->crtc_id, crtc->buffer_id,
   2.143 -                                        crtc->x, crtc->y, &conn->connector_id, 1, &crtc->mode);
   2.144 +        int ret = drm_atomic_commit(_this, dispdata->crtc->buffer_id, flags);
   2.145  
   2.146          if (ret != 0) {
   2.147 -            SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
   2.148 +            SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original videomode");
   2.149          }
   2.150      }
   2.151      /****************/
   2.152 @@ -1191,11 +1205,9 @@
   2.153          goto error;
   2.154      }
   2.155  
   2.156 -    /* Init windata fields. */
   2.157 -    windata->crtc_setup_pending = SDL_FALSE;
   2.158 +    /* Init fields. */
   2.159      windata->egl_surface_dirty  = SDL_FALSE;
   2.160  
   2.161 -
   2.162      /* First remember that certain functions in SDL_Video.c will call *_SetDisplayMode when the
   2.163         SDL_WINDOW_FULLSCREEN is set and SDL_WINDOW_FULLSCREEN_DESKTOP is not set.
   2.164         So I am determining here that the behavior when creating an SDL_Window() in KMSDRM, is:
     3.1 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.h	Wed Aug 05 15:28:51 2020 +0200
     3.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h	Wed Aug 05 18:55:22 2020 +0200
     3.3 @@ -75,14 +75,13 @@
     3.4      drmModeObjectProperties *connector_props;
     3.5      drmModePropertyRes **connector_props_info;
     3.6  
     3.7 -    int crtc_index;
     3.8 -
     3.9      int kms_in_fence_fd;
    3.10      int kms_out_fence_fd;
    3.11  
    3.12      EGLSyncKHR kms_fence; /* Signaled when kms completes changes requested in atomic iotcl (pageflip, etc). */
    3.13      EGLSyncKHR gpu_fence; /* Signaled when GPU rendering is done. */
    3.14  
    3.15 +    SDL_bool modeset_pending;
    3.16  } SDL_DisplayData;
    3.17  
    3.18  
    3.19 @@ -93,7 +92,6 @@
    3.20      struct gbm_bo *bo;
    3.21      struct gbm_bo *next_bo;
    3.22      struct gbm_bo *crtc_bo;
    3.23 -    SDL_bool crtc_setup_pending;
    3.24  #if SDL_VIDEO_OPENGL_EGL
    3.25      SDL_bool egl_surface_dirty;
    3.26      EGLSurface egl_surface;