src/video/kmsdrm/SDL_kmsdrmvideo.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 02 Aug 2017 10:22:48 -0700
changeset 11175 cbc6a8a5b701
child 11176 9397a2d41d6b
permissions -rw-r--r--
Fixed bug 3690 - SDL2 KMS/DRM render context support

Manuel

The attached patch adds support for KMS/DRM context graphics.

It builds with no problem on X86_64 GNU/Linux systems, provided the needed libraries are present, and on ARM GNU/Linux systems that have KMS/DRM support and a GLES2 implementation.
Tested on Raspberry Pi: KMS/DRM is what the Raspberry Pi will use as default in the near future, once the propietary DispmanX API by Broadcom is overtaken by open graphics stack, it's possible to boot current Raspbian system in KMS mode by adding "dtoverlay=vc4-kms-v3d" to config.txt on Raspbian's boot partition.
X86 systems use KMS right away in every current GNU/Linux system.

Simple build instructions:

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