1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#ifndef SDL_kmsdrmvideo_h
25#define SDL_kmsdrmvideo_h
26
27#include "../SDL_sysvideo.h"
28
29#include <fcntl.h>
30#include <unistd.h>
31#include <xf86drm.h>
32#include <xf86drmMode.h>
33#include <gbm.h>
34#include <EGL/egl.h>
35
36#ifndef DRM_FORMAT_MOD_INVALID
37#define DRM_FORMAT_MOD_INVALID 0x00ffffffffffffffULL
38#endif
39
40#ifndef DRM_MODE_FB_MODIFIERS
41#define DRM_MODE_FB_MODIFIERS 2
42#endif
43
44#ifndef DRM_MODE_PAGE_FLIP_ASYNC
45#define DRM_MODE_PAGE_FLIP_ASYNC 2
46#endif
47
48#ifndef DRM_MODE_OBJECT_CONNECTOR
49#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
50#endif
51
52#ifndef DRM_MODE_OBJECT_CRTC
53#define DRM_MODE_OBJECT_CRTC 0xcccccccc
54#endif
55
56#ifndef DRM_CAP_ASYNC_PAGE_FLIP
57#define DRM_CAP_ASYNC_PAGE_FLIP 7
58#endif
59
60#ifndef DRM_CAP_CURSOR_WIDTH
61#define DRM_CAP_CURSOR_WIDTH 8
62#endif
63
64#ifndef DRM_CAP_CURSOR_HEIGHT
65#define DRM_CAP_CURSOR_HEIGHT 9
66#endif
67
68#ifndef GBM_FORMAT_ARGB8888
69#define GBM_FORMAT_ARGB8888 ((uint32_t)('A') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24))
70#define GBM_BO_USE_CURSOR (1 << 1)
71#define GBM_BO_USE_WRITE (1 << 3)
72#define GBM_BO_USE_LINEAR (1 << 4)
73#endif
74
75struct SDL_VideoData
76{
77 int devindex; // device index that was passed on creation
78 int drm_fd; // DRM file desc
79 char devpath[32]; // DRM dev path.
80
81 struct gbm_device *gbm_dev;
82
83 bool video_init; // Has VideoInit succeeded?
84 bool vulkan_mode; // Are we in Vulkan mode? One VK window is enough to be.
85 bool async_pageflip_support; // Does the hardware support async. pageflips?
86
87 SDL_Window **windows;
88 int max_windows;
89 int num_windows;
90
91 /* Even if we have several displays, we only have to
92 open 1 FD and create 1 gbm device. */
93 bool gbm_init;
94
95};
96
97struct SDL_DisplayModeData
98{
99 int mode_index;
100};
101
102struct SDL_DisplayData
103{
104 drmModeConnector *connector;
105 drmModeCrtc *crtc;
106 drmModeModeInfo mode;
107 drmModeModeInfo original_mode;
108 drmModeModeInfo fullscreen_mode;
109
110 drmModeCrtc *saved_crtc; // CRTC to restore on quit
111 bool saved_vrr;
112
113 /* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's internal struct,
114 because setting/unsetting up these is done on window creation/destruction,
115 where we may not have an SDL_Cursor at all (so no SDL_Cursor internal).
116 There's only one cursor GBM BO because we only support one cursor. */
117 struct gbm_bo *cursor_bo;
118 int cursor_bo_drm_fd;
119 uint64_t cursor_w, cursor_h;
120
121 bool default_cursor_init;
122};
123
124struct SDL_WindowData
125{
126 SDL_VideoData *viddata;
127 /* SDL internals expect EGL surface to be here, and in KMSDRM the GBM surface is
128 what supports the EGL surface on the driver side, so all these surfaces and buffers
129 are expected to be here, in the struct pointed by SDL_Window internal pointer:
130 this one. So don't try to move these to dispdata! */
131 struct gbm_surface *gs;
132 struct gbm_bo *bo;
133 struct gbm_bo *next_bo;
134
135 bool waiting_for_flip;
136 bool double_buffer;
137
138 EGLSurface egl_surface;
139 bool egl_surface_dirty;
140};
141
142typedef struct KMSDRM_FBInfo
143{
144 int drm_fd; // DRM file desc
145 uint32_t fb_id; // DRM framebuffer ID
146} KMSDRM_FBInfo;
147
148// Helper functions
149extern bool KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window);
150extern KMSDRM_FBInfo *KMSDRM_FBFromBO(SDL_VideoDevice *_this, struct gbm_bo *bo);
151extern KMSDRM_FBInfo *KMSDRM_FBFromBO2(SDL_VideoDevice *_this, struct gbm_bo *bo, int w, int h);
152extern bool KMSDRM_WaitPageflip(SDL_VideoDevice *_this, SDL_WindowData *windata);
153
154/****************************************************************************/
155// SDL_VideoDevice functions declaration
156/****************************************************************************/
157
158// Display and window functions
159extern bool KMSDRM_VideoInit(SDL_VideoDevice *_this);
160extern void KMSDRM_VideoQuit(SDL_VideoDevice *_this);
161extern bool KMSDRM_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
162extern bool KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
163extern bool KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
164extern void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
165extern bool KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window);
166extern void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
167extern SDL_FullscreenResult KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_FullscreenOp fullscreen);
168extern void KMSDRM_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window);
169extern void KMSDRM_HideWindow(SDL_VideoDevice *_this, SDL_Window *window);
170extern void KMSDRM_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window);
171extern void KMSDRM_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
172extern void KMSDRM_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
173extern void KMSDRM_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
174extern void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
175
176#endif // SDL_kmsdrmvideo_h
177