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