22 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_DRIVER_KMSDRM
27 #include "../SDL_sysvideo.h"
31 #include "../../events/SDL_mouse_c.h"
32 #include "../../events/SDL_keyboard_c.h"
34 #ifdef SDL_INPUT_LINUXEV
35 #include "../../core/linux/SDL_evdev.h"
48 #define KMSDRM_DRI_PATH "/dev/dri/"
51 check_modestting(
int devindex)
59 drm_fd = open(
device, O_RDWR | O_CLOEXEC);
62 drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd);
63 if (resources !=
NULL) {
65 KMSDRM_DRI_PATH, devindex,
66 resources->count_connectors, resources->count_encoders, resources->count_crtcs);
68 if (resources->count_connectors > 0 && resources->count_encoders > 0 && resources->count_crtcs > 0) {
71 KMSDRM_drmModeFreeResources(resources);
81 static int get_dricount(
void)
88 if (!(stat(KMSDRM_DRI_PATH, &sb) == 0
89 && S_ISDIR(sb.st_mode))) {
90 printf(
"The path %s cannot be opened or is not available\n",
95 if (
access(KMSDRM_DRI_PATH, F_OK) == -1) {
96 printf(
"The path %s cannot be opened\n",
101 folder = opendir(KMSDRM_DRI_PATH);
103 while ((
res = readdir(folder))) {
118 const int devcount = get_dricount();
121 for (
i = 0;
i < devcount;
i++) {
122 if (check_modestting(
i)) {
131 KMSDRM_Available(
void)
135 ret = get_driindex();
155 KMSDRM_Create(
int devindex)
160 if (!devindex || (devindex > 99)) {
161 devindex = get_driindex();
165 SDL_SetError(
"devindex (%d) must be between 0 and 99.\n", devindex);
189 device->driverdata = vdata;
195 device->free = KMSDRM_Destroy;
217 #if SDL_VIDEO_OPENGL_EGL
243 "KMS/DRM Video Driver",
250 KMSDRM_FBDestroyCallback(
struct gbm_bo *bo,
void *
data)
254 if (fb_info && fb_info->
drm_fd >= 0 && fb_info->
fb_id != 0) {
255 KMSDRM_drmModeRmFB(fb_info->
drm_fd, fb_info->
fb_id);
271 if (fb_info !=
NULL) {
278 if (fb_info ==
NULL) {
284 w = KMSDRM_gbm_bo_get_width(bo);
285 h = KMSDRM_gbm_bo_get_height(bo);
286 stride = KMSDRM_gbm_bo_get_stride(bo);
287 handle = KMSDRM_gbm_bo_get_handle(bo).u32;
297 KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback);
312 if (vdata->
drm_pollfd.revents & (POLLHUP | POLLERR)) {
330 KMSDRM_FlipHandler(
int fd,
unsigned int frame,
unsigned int sec,
unsigned int usec,
void *
data)
348 drmModeRes *resources =
NULL;
349 drmModeConnector *connector =
NULL;
350 drmModeEncoder *encoder =
NULL;
364 if (devname ==
NULL) {
370 vdata->
drm_fd = open(devname, O_RDWR | O_CLOEXEC);
379 vdata->
gbm = KMSDRM_gbm_create_device(vdata->
drm_fd);
386 resources = KMSDRM_drmModeGetResources(vdata->
drm_fd);
392 for (
i = 0;
i < resources->count_connectors;
i++) {
393 connector = KMSDRM_drmModeGetConnector(vdata->
drm_fd, resources->connectors[
i]);
394 if (connector ==
NULL)
397 if (connector->connection == DRM_MODE_CONNECTED &&
398 connector->count_modes > 0) {
400 connector->connector_id, connector->count_modes);
405 KMSDRM_drmModeFreeConnector(connector);
409 if (
i == resources->count_connectors) {
410 ret =
SDL_SetError(
"No currently active connector found.");
416 for (
i = 0;
i < resources->count_encoders;
i++) {
417 encoder = KMSDRM_drmModeGetEncoder(vdata->
drm_fd, resources->encoders[
i]);
422 if (encoder->encoder_id == connector->encoder_id) {
423 data->encoder_id = encoder->encoder_id;
426 for (
j = 0;
j < connector->count_encoders;
j++) {
427 if (connector->encoders[
j] == encoder->encoder_id) {
428 data->encoder_id = encoder->encoder_id;
440 KMSDRM_drmModeFreeEncoder(encoder);
444 if (
i == resources->count_encoders) {
452 for (
i = 0;
i < resources->count_crtcs;
i++) {
453 if (encoder->possible_crtcs & (1 <<
i)) {
454 encoder->crtc_id = resources->crtcs[
i];
469 data->crtc_id = encoder->crtc_id;
471 vdata->
crtc_id = encoder->crtc_id;
476 "Current mode is invalid, selecting connector's mode #0.");
477 data->cur_mode = connector->modes[0];
482 current_mode.
w =
data->cur_mode.hdisplay;
483 current_mode.
h =
data->cur_mode.vdisplay;
506 vdata->
drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
507 vdata->
drm_evctx.page_flip_handler = KMSDRM_FlipHandler;
509 #ifdef SDL_INPUT_LINUXEV
519 KMSDRM_drmModeFreeEncoder(encoder);
520 if (connector !=
NULL)
521 KMSDRM_drmModeFreeConnector(connector);
522 if (resources !=
NULL)
523 KMSDRM_drmModeFreeResources(resources);
533 KMSDRM_gbm_device_destroy(vdata->
gbm);
559 if(KMSDRM_drmModeSetCrtc(vdata->
drm_fd, crtc->crtc_id, crtc->buffer_id,
569 KMSDRM_gbm_device_destroy(vdata->
gbm);
577 #ifdef SDL_INPUT_LINUXEV
601 Uint32 surface_fmt, surface_flags;
620 surface_fmt = GBM_FORMAT_XRGB8888;
621 surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
623 if (!KMSDRM_gbm_device_is_format_supported(vdata->
gbm, surface_fmt, surface_flags)) {
626 wdata->
gs = KMSDRM_gbm_surface_create(vdata->
gbm,
window->w,
window->h, surface_fmt, surface_flags);
628 #if SDL_VIDEO_OPENGL_EGL
629 if (!
_this->egl_data) {
634 SDL_EGL_SetRequiredVisualId(
_this, surface_fmt);
656 window->driverdata = wdata;
667 #if SDL_VIDEO_OPENGL_EGL
672 KMSDRM_gbm_surface_destroy(wdata->
gs);
686 KMSDRM_gbm_surface_release_buffer(
data->gs,
data->crtc_bo);
690 KMSDRM_gbm_surface_release_buffer(
data->gs,
data->next_bo);
694 KMSDRM_gbm_surface_release_buffer(
data->gs,
data->current_bo);
697 #if SDL_VIDEO_OPENGL_EGL
700 SDL_EGL_DestroySurface(
_this,
data->egl_surface);
704 KMSDRM_gbm_surface_destroy(
data->gs);
773 SDL_SetError(
"application not compiled with SDL %d.%d\n",