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