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