src/video/kmsdrm/SDL_kmsdrmvideo.c
author Brandon Schaefer <brandontschaefer@gmail.com>
Tue, 07 Nov 2017 09:10:32 -0800
changeset 11694 2ce56475ad57
parent 11658 fbfdee28682d
child 11714 f10f06ee8207
permissions -rw-r--r--
Fixed bug 3943 - General SDL_HINT_VIDEO_DOUBLE_BUFFER hint support
     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 "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 
   366     SDL_zero(current_mode);
   367 
   368     current_mode.w = vdata->saved_crtc->mode.hdisplay;
   369     current_mode.h = vdata->saved_crtc->mode.vdisplay;
   370     current_mode.refresh_rate = vdata->saved_crtc->mode.vrefresh;
   371 
   372     /* FIXME ?
   373     drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id);
   374     current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth);
   375     drmModeFreeFB(fb);
   376     */
   377     current_mode.format = SDL_PIXELFORMAT_ARGB8888;
   378 
   379     current_mode.driverdata = NULL;
   380 
   381     SDL_zero(display);
   382     display.desktop_mode = current_mode;
   383     display.current_mode = current_mode;
   384 
   385     display.driverdata = data;
   386     /* SDL_VideoQuit will later SDL_free(display.driverdata) */
   387     SDL_AddVideoDisplay(&display);
   388 
   389     /* Setup page flip handler */
   390     vdata->drm_pollfd.fd = vdata->drm_fd;
   391     vdata->drm_pollfd.events = POLLIN;
   392     vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
   393     vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler;
   394 
   395 #ifdef SDL_INPUT_LINUXEV
   396     SDL_EVDEV_Init();
   397 #endif
   398 
   399     KMSDRM_InitMouse(_this);
   400 
   401 cleanup:
   402     if (encoder != NULL)
   403         KMSDRM_drmModeFreeEncoder(encoder);
   404     if (connector != NULL)
   405         KMSDRM_drmModeFreeConnector(connector);
   406     if (resources != NULL)
   407         KMSDRM_drmModeFreeResources(resources);
   408 
   409     if (ret != 0) {
   410         /* Error (complete) cleanup */
   411         SDL_free(data);
   412         if(vdata->saved_crtc != NULL) {
   413             KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
   414             vdata->saved_crtc = NULL;
   415         }
   416         if (vdata->gbm != NULL) {
   417             KMSDRM_gbm_device_destroy(vdata->gbm);
   418             vdata->gbm = NULL;
   419         }
   420         if (vdata->drm_fd >= 0) {
   421             close(vdata->drm_fd);
   422             vdata->drm_fd = -1;
   423         }
   424     }
   425     return ret;
   426 }
   427 
   428 void
   429 KMSDRM_VideoQuit(_THIS)
   430 {
   431     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   432 
   433     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
   434 
   435     if (_this->gl_config.driver_loaded) {
   436         SDL_GL_UnloadLibrary();
   437     }
   438 
   439     if(vdata->saved_crtc != NULL) {
   440         if(vdata->drm_fd > 0 && vdata->saved_conn_id > 0) {
   441             /* Restore saved CRTC settings */
   442             drmModeCrtc *crtc = vdata->saved_crtc;
   443             if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id,
   444                                      crtc->x, crtc->y, &vdata->saved_conn_id, 1,
   445                                      &crtc->mode) != 0) {
   446                 SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
   447             }
   448         }
   449         KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
   450         vdata->saved_crtc = NULL;
   451     }
   452     if (vdata->gbm != NULL) {
   453         KMSDRM_gbm_device_destroy(vdata->gbm);
   454         vdata->gbm = NULL;
   455     }
   456     if (vdata->drm_fd >= 0) {
   457         close(vdata->drm_fd);
   458         SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd);
   459         vdata->drm_fd = -1;
   460     }
   461 #ifdef SDL_INPUT_LINUXEV
   462     SDL_EVDEV_Quit();
   463 #endif
   464 }
   465 
   466 void
   467 KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
   468 {
   469     /* Only one display mode available, the current one */
   470     SDL_AddDisplayMode(display, &display->current_mode);
   471 }
   472 
   473 int
   474 KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   475 {
   476     return 0;
   477 }
   478 
   479 int
   480 KMSDRM_CreateWindow(_THIS, SDL_Window * window)
   481 {
   482     SDL_WindowData *wdata;
   483     SDL_VideoDisplay *display;
   484     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   485     Uint32 surface_fmt, surface_flags;
   486 
   487     /* Allocate window internal data */
   488     wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
   489     if (wdata == NULL) {
   490         SDL_OutOfMemory();
   491         goto error;
   492     }
   493 
   494     wdata->waiting_for_flip = SDL_FALSE;
   495     display = SDL_GetDisplayForWindow(window);
   496 
   497     /* Windows have one size for now */
   498     window->w = display->desktop_mode.w;
   499     window->h = display->desktop_mode.h;
   500 
   501     /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */
   502     window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
   503 
   504     surface_fmt = GBM_FORMAT_XRGB8888;
   505     surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
   506 
   507     if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) {
   508         SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
   509     }
   510     wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags);
   511 
   512 #if SDL_VIDEO_OPENGL_EGL
   513     if (!_this->egl_data) {
   514         if (SDL_GL_LoadLibrary(NULL) < 0) {
   515             goto error;
   516         }
   517     }
   518     wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs);
   519 
   520     if (wdata->egl_surface == EGL_NO_SURFACE) {
   521         SDL_SetError("Could not create EGL window surface");
   522         goto error;
   523     }
   524 #endif /* SDL_VIDEO_OPENGL_EGL */
   525 
   526     /* In case we want low-latency, double-buffer video, we take note here */
   527     wdata->double_buffer = SDL_FALSE;
   528     if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
   529         wdata->double_buffer = SDL_TRUE;
   530     }
   531 
   532     /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want
   533        drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
   534        need to do eglSwapBuffers so we can get a valid GBM buffer object to call
   535        drmModeSetCrtc on it. */
   536     wdata->crtc_ready = SDL_FALSE;
   537 
   538     /* Setup driver data for this window */
   539     window->driverdata = wdata;
   540 
   541     /* One window, it always has focus */
   542     SDL_SetMouseFocus(window);
   543     SDL_SetKeyboardFocus(window);
   544 
   545     /* Window has been successfully created */
   546     return 0;
   547 
   548 error:
   549     if (wdata != NULL) {
   550 #if SDL_VIDEO_OPENGL_EGL
   551         if (wdata->egl_surface != EGL_NO_SURFACE)
   552             SDL_EGL_DestroySurface(_this, wdata->egl_surface);
   553 #endif /* SDL_VIDEO_OPENGL_EGL */
   554         if (wdata->gs != NULL)
   555             KMSDRM_gbm_surface_destroy(wdata->gs);
   556         SDL_free(wdata);
   557     }
   558     return -1;
   559 }
   560 
   561 void
   562 KMSDRM_DestroyWindow(_THIS, SDL_Window * window)
   563 {
   564     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   565     if(data) {
   566         /* Wait for any pending page flips and unlock buffer */
   567         KMSDRM_WaitPageFlip(_this, data, -1);
   568         if (data->next_bo != NULL) {
   569             KMSDRM_gbm_surface_release_buffer(data->gs, data->next_bo);
   570             data->next_bo = NULL;
   571         }
   572         if (data->current_bo != NULL) {
   573             KMSDRM_gbm_surface_release_buffer(data->gs, data->current_bo);
   574             data->current_bo = NULL;
   575         }
   576 #if SDL_VIDEO_OPENGL_EGL
   577         SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   578         if (data->egl_surface != EGL_NO_SURFACE) {
   579             SDL_EGL_DestroySurface(_this, data->egl_surface);
   580         }
   581 #endif /* SDL_VIDEO_OPENGL_EGL */
   582         if (data->gs != NULL) {
   583             KMSDRM_gbm_surface_destroy(data->gs);
   584             data->gs = NULL;
   585         }
   586         SDL_free(data);
   587         window->driverdata = NULL;
   588     }
   589 }
   590 
   591 int
   592 KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   593 {
   594     return -1;
   595 }
   596 
   597 void
   598 KMSDRM_SetWindowTitle(_THIS, SDL_Window * window)
   599 {
   600 }
   601 void
   602 KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   603 {
   604 }
   605 void
   606 KMSDRM_SetWindowPosition(_THIS, SDL_Window * window)
   607 {
   608 }
   609 void
   610 KMSDRM_SetWindowSize(_THIS, SDL_Window * window)
   611 {
   612 }
   613 void
   614 KMSDRM_ShowWindow(_THIS, SDL_Window * window)
   615 {
   616 }
   617 void
   618 KMSDRM_HideWindow(_THIS, SDL_Window * window)
   619 {
   620 }
   621 void
   622 KMSDRM_RaiseWindow(_THIS, SDL_Window * window)
   623 {
   624 }
   625 void
   626 KMSDRM_MaximizeWindow(_THIS, SDL_Window * window)
   627 {
   628 }
   629 void
   630 KMSDRM_MinimizeWindow(_THIS, SDL_Window * window)
   631 {
   632 }
   633 void
   634 KMSDRM_RestoreWindow(_THIS, SDL_Window * window)
   635 {
   636 }
   637 void
   638 KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
   639 {
   640 
   641 }
   642 
   643 /*****************************************************************************/
   644 /* SDL Window Manager function                                               */
   645 /*****************************************************************************/
   646 SDL_bool
   647 KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
   648 {
   649     if (info->version.major <= SDL_MAJOR_VERSION) {
   650         return SDL_TRUE;
   651     } else {
   652         SDL_SetError("application not compiled with SDL %d.%d\n",
   653                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   654         return SDL_FALSE;
   655     }
   656 
   657     /* Failed to get window manager information */
   658     return SDL_FALSE;
   659 }
   660 
   661 #endif /* SDL_VIDEO_DRIVER_KMSDRM */
   662 
   663 /* vi: set ts=4 sw=4 expandtab: */