src/video/kmsdrm/SDL_kmsdrmvideo.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 21 Oct 2017 04:20:57 -0700
changeset 11643 273acc67dbfa
parent 11442 11413fa29401
child 11658 fbfdee28682d
permissions -rw-r--r--
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).
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #include "../../SDL_internal.h"
    23 
    24 #if SDL_VIDEO_DRIVER_KMSDRM
    25 
    26 /* SDL internals */
    27 #include "../SDL_sysvideo.h"
    28 #include "SDL_syswm.h"
    29 #include "SDL_log.h"
    30 #include "../../events/SDL_mouse_c.h"
    31 #include "../../events/SDL_keyboard_c.h"
    32 
    33 #ifdef SDL_INPUT_LINUXEV
    34 #include "../../core/linux/SDL_evdev.h"
    35 #endif
    36 
    37 /* KMS/DRM declarations */
    38 #include "SDL_kmsdrmvideo.h"
    39 #include "SDL_kmsdrmevents.h"
    40 #include "SDL_kmsdrmopengles.h"
    41 #include "SDL_kmsdrmmouse.h"
    42 #include "SDL_kmsdrmdyn.h"
    43 
    44 #define KMSDRM_DRI_CARD_0 "/dev/dri/card0"
    45 
    46 static int
    47 KMSDRM_Available(void)
    48 {
    49     int available = 0;
    50 
    51     int drm_fd = open(KMSDRM_DRI_CARD_0, O_RDWR | O_CLOEXEC);
    52     if (drm_fd >= 0) {
    53         if (SDL_KMSDRM_LoadSymbols()) {
    54             drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd);
    55             if (resources != NULL) {
    56                 available = 1;
    57                 KMSDRM_drmModeFreeResources(resources);
    58             }
    59             SDL_KMSDRM_UnloadSymbols();
    60         }
    61         close(drm_fd);
    62     }
    63 
    64     return available;
    65 }
    66 
    67 static void
    68 KMSDRM_Destroy(SDL_VideoDevice * device)
    69 {
    70     if (device->driverdata != NULL) {
    71         SDL_free(device->driverdata);
    72         device->driverdata = NULL;
    73     }
    74 
    75     SDL_free(device);
    76     SDL_KMSDRM_UnloadSymbols();
    77 }
    78 
    79 static SDL_VideoDevice *
    80 KMSDRM_Create(int devindex)
    81 {
    82     SDL_VideoDevice *device;
    83     SDL_VideoData *vdata;
    84 
    85     if (devindex < 0 || devindex > 99) {
    86         SDL_SetError("devindex (%d) must be between 0 and 99.\n", devindex);
    87         return NULL;
    88     }
    89 
    90     if (!SDL_KMSDRM_LoadSymbols()) {
    91         return NULL;
    92     }
    93 
    94     /* Initialize SDL_VideoDevice structure */
    95     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    96     if (device == NULL) {
    97         SDL_OutOfMemory();
    98         return NULL;
    99     }
   100 
   101     /* Initialize internal data */
   102     vdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
   103     if (vdata == NULL) {
   104         SDL_OutOfMemory();
   105         goto cleanup;
   106     }
   107     vdata->devindex = devindex;
   108     vdata->drm_fd = -1;
   109 
   110     device->driverdata = vdata;
   111 
   112     /* Setup amount of available displays and current display */
   113     device->num_displays = 0;
   114 
   115     /* Set device free function */
   116     device->free = KMSDRM_Destroy;
   117 
   118     /* Setup all functions which we can handle */
   119     device->VideoInit = KMSDRM_VideoInit;
   120     device->VideoQuit = KMSDRM_VideoQuit;
   121     device->GetDisplayModes = KMSDRM_GetDisplayModes;
   122     device->SetDisplayMode = KMSDRM_SetDisplayMode;
   123     device->CreateSDLWindow = KMSDRM_CreateWindow;
   124     device->CreateSDLWindowFrom = KMSDRM_CreateWindowFrom;
   125     device->SetWindowTitle = KMSDRM_SetWindowTitle;
   126     device->SetWindowIcon = KMSDRM_SetWindowIcon;
   127     device->SetWindowPosition = KMSDRM_SetWindowPosition;
   128     device->SetWindowSize = KMSDRM_SetWindowSize;
   129     device->ShowWindow = KMSDRM_ShowWindow;
   130     device->HideWindow = KMSDRM_HideWindow;
   131     device->RaiseWindow = KMSDRM_RaiseWindow;
   132     device->MaximizeWindow = KMSDRM_MaximizeWindow;
   133     device->MinimizeWindow = KMSDRM_MinimizeWindow;
   134     device->RestoreWindow = KMSDRM_RestoreWindow;
   135     device->SetWindowGrab = KMSDRM_SetWindowGrab;
   136     device->DestroyWindow = KMSDRM_DestroyWindow;
   137     device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo;
   138 #if SDL_VIDEO_OPENGL_EGL
   139     device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary;
   140     device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress;
   141     device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary;
   142     device->GL_CreateContext = KMSDRM_GLES_CreateContext;
   143     device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
   144     device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
   145     device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
   146     device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
   147     device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
   148 #endif
   149 
   150     device->PumpEvents = KMSDRM_PumpEvents;
   151 
   152     return device;
   153 
   154 cleanup:
   155     if (device != NULL)
   156         SDL_free(device);
   157     if (vdata != NULL)
   158         SDL_free(vdata);
   159     return NULL;
   160 }
   161 
   162 VideoBootStrap KMSDRM_bootstrap = {
   163     "KMSDRM",
   164     "KMS/DRM Video Driver",
   165     KMSDRM_Available,
   166     KMSDRM_Create
   167 };
   168 
   169 
   170 static void
   171 KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
   172 {
   173     KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data;
   174 
   175     if (fb_info && fb_info->drm_fd > 0 && fb_info->fb_id != 0) {
   176         KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id);
   177         SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id);
   178     }
   179 
   180     free(fb_info);
   181 }
   182 
   183 KMSDRM_FBInfo *
   184 KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
   185 {
   186     uint32_t w, h, stride, handle;
   187     int ret;
   188     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   189     KMSDRM_FBInfo *fb_info;
   190 
   191     fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo);
   192     if (fb_info != NULL) {
   193         /* Have a previously used framebuffer, return it */
   194         return fb_info;
   195     }
   196 
   197     /* Here a new DRM FB must be created */
   198     fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo));
   199     if (fb_info == NULL) {
   200         SDL_OutOfMemory();
   201         return NULL;
   202     }
   203     fb_info->drm_fd = vdata->drm_fd;
   204 
   205     w  = KMSDRM_gbm_bo_get_width(bo);
   206     h = KMSDRM_gbm_bo_get_height(bo);
   207     stride = KMSDRM_gbm_bo_get_stride(bo);
   208     handle = KMSDRM_gbm_bo_get_handle(bo).u32;
   209 
   210     ret = KMSDRM_drmModeAddFB(vdata->drm_fd, w, h, 24, 32, stride, handle, &fb_info->fb_id);
   211     if (ret < 0) {
   212        free(fb_info);
   213        return NULL;
   214     }
   215     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "New DRM FB (%u): %ux%u, stride %u from BO %p", fb_info->fb_id, w, h, stride, (void *)bo);
   216 
   217     /* Associate our DRM framebuffer with this buffer object */
   218     KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback);
   219     return fb_info;
   220 }
   221 
   222 SDL_bool
   223 KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout) {
   224     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   225 
   226     while (wdata->waiting_for_flip) {
   227         vdata->drm_pollfd.revents = 0;
   228         if (poll(&vdata->drm_pollfd, 1, timeout) < 0) {
   229             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
   230             return SDL_FALSE;
   231         }
   232 
   233         if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) {
   234             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error");
   235             return SDL_FALSE;
   236         }
   237 
   238         if (vdata->drm_pollfd.revents & POLLIN) {
   239             /* Page flip? If so, drmHandleEvent will unset wdata->waiting_for_flip */
   240             KMSDRM_drmHandleEvent(vdata->drm_fd, &vdata->drm_evctx);
   241         } else {
   242             /* Timed out and page flip didn't happen */
   243             SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip");
   244             return SDL_FALSE;
   245         }
   246     }
   247     return SDL_TRUE;
   248 }
   249 
   250 static void
   251 KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
   252 {
   253     *((SDL_bool *) data) = SDL_FALSE;
   254 }
   255 
   256 
   257 /*****************************************************************************/
   258 /* SDL Video and Display initialization/handling functions                   */
   259 /* _this is a SDL_VideoDevice *                                              */
   260 /*****************************************************************************/
   261 int
   262 KMSDRM_VideoInit(_THIS)
   263 {
   264     int i;
   265     int ret = 0;
   266     char *devname;
   267     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   268     drmModeRes *resources = NULL;
   269     drmModeConnector *connector = NULL;
   270     drmModeEncoder *encoder = NULL;
   271     SDL_DisplayMode current_mode;
   272     SDL_VideoDisplay display;
   273 
   274     /* Allocate display internal data */
   275     SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
   276     if (data == NULL) {
   277         return SDL_OutOfMemory();
   278     }
   279 
   280     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()");
   281 
   282     /* Open /dev/dri/cardNN */
   283     devname = (char *) SDL_calloc(1, 16);
   284     if (devname == NULL) {
   285         ret = SDL_OutOfMemory();
   286         goto cleanup;
   287     }
   288     SDL_snprintf(devname, 16, "/dev/dri/card%d", vdata->devindex);
   289     vdata->drm_fd = open(devname, O_RDWR | O_CLOEXEC);
   290     SDL_free(devname);
   291 
   292     if (vdata->drm_fd < 0) {
   293         ret = SDL_SetError("Could not open /dev/dri/card%d.", vdata->devindex);
   294         goto cleanup;
   295     }
   296     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd);
   297 
   298     vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd);
   299     if (vdata->gbm == NULL) {
   300         ret = SDL_SetError("Couldn't create gbm device.");
   301         goto cleanup;
   302     }
   303 
   304     /* Find the first available connector with modes */
   305     resources = KMSDRM_drmModeGetResources(vdata->drm_fd);
   306     if (!resources) {
   307         ret = SDL_SetError("drmModeGetResources(%d) failed", vdata->drm_fd);
   308         goto cleanup;
   309     }
   310 
   311     for (i = 0; i < resources->count_connectors; i++) {
   312         connector = KMSDRM_drmModeGetConnector(vdata->drm_fd, resources->connectors[i]);
   313         if (connector == NULL)
   314             continue;
   315 
   316         if (connector->connection == DRM_MODE_CONNECTED &&
   317             connector->count_modes > 0) {
   318             SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found connector %d with %d modes.",
   319                          connector->connector_id, connector->count_modes);
   320             vdata->saved_conn_id = connector->connector_id;
   321             break;
   322         }
   323 
   324         KMSDRM_drmModeFreeConnector(connector);
   325         connector = NULL;
   326     }
   327 
   328     if (i == resources->count_connectors) {
   329         ret = SDL_SetError("No currently active connector found.");
   330         goto cleanup;
   331     }
   332 
   333     for (i = 0; i < resources->count_encoders; i++) {
   334         encoder = KMSDRM_drmModeGetEncoder(vdata->drm_fd, resources->encoders[i]);
   335 
   336         if (encoder == NULL)
   337             continue;
   338 
   339         if (encoder->encoder_id == connector->encoder_id) {
   340             SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found encoder %d.", encoder->encoder_id);
   341             data->encoder_id = encoder->encoder_id;
   342             break;
   343         }
   344 
   345         KMSDRM_drmModeFreeEncoder(encoder);
   346         encoder = NULL;
   347     }
   348 
   349     if (i == resources->count_encoders) {
   350         ret = SDL_SetError("No connected encoder found.");
   351         goto cleanup;
   352     }
   353 
   354     vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id);
   355     if (vdata->saved_crtc == NULL) {
   356         ret = SDL_SetError("No CRTC found.");
   357         goto cleanup;
   358     }
   359     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u",
   360                  vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x,
   361                  vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height);
   362     data->crtc_id = encoder->crtc_id;
   363     data->cur_mode = vdata->saved_crtc->mode;
   364 
   365     SDL_zero(current_mode);
   366 
   367     current_mode.w = vdata->saved_crtc->mode.hdisplay;
   368     current_mode.h = vdata->saved_crtc->mode.vdisplay;
   369     current_mode.refresh_rate = vdata->saved_crtc->mode.vrefresh;
   370 
   371     /* FIXME ?
   372     drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id);
   373     current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth);
   374     drmModeFreeFB(fb);
   375     */
   376     current_mode.format = SDL_PIXELFORMAT_ARGB8888;
   377 
   378     current_mode.driverdata = NULL;
   379 
   380     SDL_zero(display);
   381     display.desktop_mode = current_mode;
   382     display.current_mode = current_mode;
   383 
   384     display.driverdata = data;
   385     /* SDL_VideoQuit will later SDL_free(display.driverdata) */
   386     SDL_AddVideoDisplay(&display);
   387 
   388     /* Setup page flip handler */
   389     vdata->drm_pollfd.fd = vdata->drm_fd;
   390     vdata->drm_pollfd.events = POLLIN;
   391     vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
   392     vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler;
   393 
   394 #ifdef SDL_INPUT_LINUXEV
   395     SDL_EVDEV_Init();
   396 #endif
   397 
   398     KMSDRM_InitMouse(_this);
   399 
   400 cleanup:
   401     if (encoder != NULL)
   402         KMSDRM_drmModeFreeEncoder(encoder);
   403     if (connector != NULL)
   404         KMSDRM_drmModeFreeConnector(connector);
   405     if (resources != NULL)
   406         KMSDRM_drmModeFreeResources(resources);
   407 
   408     if (ret != 0) {
   409         /* Error (complete) cleanup */
   410         SDL_free(data);
   411         if(vdata->saved_crtc != NULL) {
   412             KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
   413             vdata->saved_crtc = NULL;
   414         }
   415         if (vdata->gbm != NULL) {
   416             KMSDRM_gbm_device_destroy(vdata->gbm);
   417             vdata->gbm = NULL;
   418         }
   419         if (vdata->drm_fd >= 0) {
   420             close(vdata->drm_fd);
   421             vdata->drm_fd = -1;
   422         }
   423     }
   424     return ret;
   425 }
   426 
   427 void
   428 KMSDRM_VideoQuit(_THIS)
   429 {
   430     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   431 
   432     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
   433 
   434     if (_this->gl_config.driver_loaded) {
   435         SDL_GL_UnloadLibrary();
   436     }
   437 
   438     if(vdata->saved_crtc != NULL) {
   439         if(vdata->drm_fd > 0 && vdata->saved_conn_id > 0) {
   440             /* Restore saved CRTC settings */
   441             drmModeCrtc *crtc = vdata->saved_crtc;
   442             if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id,
   443                                      crtc->x, crtc->y, &vdata->saved_conn_id, 1,
   444                                      &crtc->mode) != 0) {
   445                 SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
   446             }
   447         }
   448         KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
   449         vdata->saved_crtc = NULL;
   450     }
   451     if (vdata->gbm != NULL) {
   452         KMSDRM_gbm_device_destroy(vdata->gbm);
   453         vdata->gbm = NULL;
   454     }
   455     if (vdata->drm_fd >= 0) {
   456         close(vdata->drm_fd);
   457         SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd);
   458         vdata->drm_fd = -1;
   459     }
   460 #ifdef SDL_INPUT_LINUXEV
   461     SDL_EVDEV_Quit();
   462 #endif
   463 }
   464 
   465 void
   466 KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
   467 {
   468     /* Only one display mode available, the current one */
   469     SDL_AddDisplayMode(display, &display->current_mode);
   470 }
   471 
   472 int
   473 KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   474 {
   475     return 0;
   476 }
   477 
   478 int
   479 KMSDRM_CreateWindow(_THIS, SDL_Window * window)
   480 {
   481     SDL_WindowData *wdata;
   482     SDL_VideoDisplay *display;
   483     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   484     Uint32 surface_fmt, surface_flags;
   485 
   486     /* Allocate window internal data */
   487     wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
   488     if (wdata == NULL) {
   489         SDL_OutOfMemory();
   490         goto error;
   491     }
   492 
   493     wdata->waiting_for_flip = SDL_FALSE;
   494     display = SDL_GetDisplayForWindow(window);
   495 
   496     /* Windows have one size for now */
   497     window->w = display->desktop_mode.w;
   498     window->h = display->desktop_mode.h;
   499 
   500     /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */
   501     window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
   502 
   503     surface_fmt = GBM_FORMAT_XRGB8888;
   504     surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
   505 
   506     if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) {
   507         SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
   508     }
   509     wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags);
   510 
   511 #if SDL_VIDEO_OPENGL_EGL
   512     if (!_this->egl_data) {
   513         if (SDL_GL_LoadLibrary(NULL) < 0) {
   514             goto error;
   515         }
   516     }
   517     wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs);
   518 
   519     if (wdata->egl_surface == EGL_NO_SURFACE) {
   520         SDL_SetError("Could not create EGL window surface");
   521         goto error;
   522     }
   523 #endif /* SDL_VIDEO_OPENGL_EGL */
   524 
   525     /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want
   526        drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
   527        need to do eglSwapBuffers so we can get a valid GBM buffer object to call 
   528        drmModeSetCrtc on it. */
   529     wdata->crtc_ready = SDL_FALSE;    
   530 
   531     /* Setup driver data for this window */
   532     window->driverdata = wdata;
   533 
   534     /* One window, it always has focus */
   535     SDL_SetMouseFocus(window);
   536     SDL_SetKeyboardFocus(window);
   537 
   538     /* Window has been successfully created */
   539     return 0;
   540 
   541 error:
   542     if (wdata != NULL) {
   543 #if SDL_VIDEO_OPENGL_EGL
   544         if (wdata->egl_surface != EGL_NO_SURFACE)
   545             SDL_EGL_DestroySurface(_this, wdata->egl_surface);
   546 #endif /* SDL_VIDEO_OPENGL_EGL */
   547         if (wdata->gs != NULL)
   548             KMSDRM_gbm_surface_destroy(wdata->gs);
   549         SDL_free(wdata);
   550     }
   551     return -1;
   552 }
   553 
   554 void
   555 KMSDRM_DestroyWindow(_THIS, SDL_Window * window)
   556 {
   557     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   558     if(data) {
   559         /* Wait for any pending page flips and unlock buffer */
   560         KMSDRM_WaitPageFlip(_this, data, -1);
   561         if (data->next_bo != NULL) {
   562             KMSDRM_gbm_surface_release_buffer(data->gs, data->next_bo);
   563             data->next_bo = NULL;
   564         }
   565         if (data->current_bo != NULL) {
   566             KMSDRM_gbm_surface_release_buffer(data->gs, data->current_bo);
   567             data->current_bo = NULL;
   568         }
   569 #if SDL_VIDEO_OPENGL_EGL
   570         SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   571         if (data->egl_surface != EGL_NO_SURFACE) {
   572             SDL_EGL_DestroySurface(_this, data->egl_surface);
   573         }
   574 #endif /* SDL_VIDEO_OPENGL_EGL */
   575         if (data->gs != NULL) {
   576             KMSDRM_gbm_surface_destroy(data->gs);
   577             data->gs = NULL;
   578         }
   579         SDL_free(data);
   580         window->driverdata = NULL;
   581     }
   582 }
   583 
   584 int
   585 KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   586 {
   587     return -1;
   588 }
   589 
   590 void
   591 KMSDRM_SetWindowTitle(_THIS, SDL_Window * window)
   592 {
   593 }
   594 void
   595 KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   596 {
   597 }
   598 void
   599 KMSDRM_SetWindowPosition(_THIS, SDL_Window * window)
   600 {
   601 }
   602 void
   603 KMSDRM_SetWindowSize(_THIS, SDL_Window * window)
   604 {
   605 }
   606 void
   607 KMSDRM_ShowWindow(_THIS, SDL_Window * window)
   608 {
   609 }
   610 void
   611 KMSDRM_HideWindow(_THIS, SDL_Window * window)
   612 {
   613 }
   614 void
   615 KMSDRM_RaiseWindow(_THIS, SDL_Window * window)
   616 {
   617 }
   618 void
   619 KMSDRM_MaximizeWindow(_THIS, SDL_Window * window)
   620 {
   621 }
   622 void
   623 KMSDRM_MinimizeWindow(_THIS, SDL_Window * window)
   624 {
   625 }
   626 void
   627 KMSDRM_RestoreWindow(_THIS, SDL_Window * window)
   628 {
   629 }
   630 void
   631 KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   632 {
   633 
   634 }
   635 
   636 /*****************************************************************************/
   637 /* SDL Window Manager function                                               */
   638 /*****************************************************************************/
   639 SDL_bool
   640 KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
   641 {
   642     if (info->version.major <= SDL_MAJOR_VERSION) {
   643         return SDL_TRUE;
   644     } else {
   645         SDL_SetError("application not compiled with SDL %d.%d\n",
   646                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   647         return SDL_FALSE;
   648     }
   649 
   650     /* Failed to get window manager information */
   651     return SDL_FALSE;
   652 }
   653 
   654 #endif /* SDL_VIDEO_DRIVER_KMSDRM */
   655 
   656 /* vi: set ts=4 sw=4 expandtab: */