src/video/kmsdrm/SDL_kmsdrmvideo.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 31 Oct 2018 15:16:51 -0700
changeset 12376 cfc65d4d49ae
parent 12310 18f3294b230e
child 12440 2b450a35f471
permissions -rw-r--r--
Fixed bug 4349 - SDL_CreateWindow fails with KMS/DRM after upgrading Mesa to 18.2.3

Rainer Sabelka

After I did an upgrade of my arch Linux installation (resulting in an update of Mesa to version 18.2.3), all my SDL2 applications which use the KMS/DRM driver stopped working.
Reason: Creating a Window with SDL_CreateWindow failed because the call to EGL
eglCreateWindowSurface() returns an error "EGL_BAD_MATCH".
After investigating with the debugger I figured, that the configuration, which has been selected from the output of eglChooseConfig(), has an "EGL_NATIVE_VISUAL_ID" which does not match the "format" of the underlying gbm surface.

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