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/"
51check_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);
81static 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)) {
131KMSDRM_Available(
void)
135 ret = get_driindex();
155KMSDRM_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",
250KMSDRM_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)) {
330KMSDRM_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",
#define SDL_GL_LoadLibrary
#define SDL_GetHintBoolean
#define SDL_GL_UnloadLibrary
#define SDL_OutOfMemory()
#define SDL_HINT_VIDEO_DOUBLE_BUFFER
Tell the video driver that we only want a double buffer.
void SDL_SetKeyboardFocus(SDL_Window *window)
int SDL_KMSDRM_LoadSymbols(void)
void SDL_KMSDRM_UnloadSymbols(void)
void KMSDRM_PumpEvents(_THIS)
void KMSDRM_InitMouse(_THIS)
void KMSDRM_RaiseWindow(_THIS, SDL_Window *window)
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval)
void KMSDRM_RestoreWindow(_THIS, SDL_Window *window)
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout)
int KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
void KMSDRM_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
void KMSDRM_ShowWindow(_THIS, SDL_Window *window)
int KMSDRM_GLES_LoadLibrary(_THIS, const char *path)
void KMSDRM_MaximizeWindow(_THIS, SDL_Window *window)
int KMSDRM_CreateWindow(_THIS, SDL_Window *window)
void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
void KMSDRM_SetWindowSize(_THIS, SDL_Window *window)
void KMSDRM_SetWindowPosition(_THIS, SDL_Window *window)
void KMSDRM_GLES_DeleteContext(_THIS, SDL_GLContext context)
void KMSDRM_HideWindow(_THIS, SDL_Window *window)
void KMSDRM_MinimizeWindow(_THIS, SDL_Window *window)
void KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
void KMSDRM_VideoQuit(_THIS)
int KMSDRM_VideoInit(_THIS)
void KMSDRM_SetWindowTitle(_THIS, SDL_Window *window)
void * KMSDRM_GLES_GetProcAddress(_THIS, const char *proc)
SDL_bool KMSDRM_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
int KMSDRM_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window *window)
void KMSDRM_GLES_UnloadLibrary(_THIS)
int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
KMSDRM_FBInfo * KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
int KMSDRM_GLES_GetSwapInterval(_THIS)
int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
void KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
void SDL_SetMouseFocus(SDL_Window *window)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLbitfield GLuint64 timeout
GLuint GLint GLboolean GLint GLenum access
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_ARGB8888
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
VideoBootStrap KMSDRM_bootstrap
#define SDL_MINOR_VERSION
#define SDL_MAJOR_VERSION
static SDL_VideoDevice * _this
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
EGLImageKHR EGLint EGLint * handle
EGLSurface EGLNativeWindowType * window
static SDL_AudioDeviceID device
The structure that defines a display mode.
A collection of pixels used in software blitting.
drmEventContext drm_evctx
struct SDL_VideoDevice::@262 gl_config
SDL_DisplayMode desktop_mode
SDL_DisplayMode current_mode
SDL_bool waiting_for_flip
The type used to identify a window.
static void cleanup(void)