Skip to content

Latest commit

 

History

History
1861 lines (1512 loc) · 59.8 KB

SDL_kmsdrmvideo.c

File metadata and controls

1861 lines (1512 loc) · 59.8 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 17, 2020
Jan 17, 2020
3
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Aug 25, 2020
Aug 25, 2020
4
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_KMSDRM
/* SDL internals */
#include "../SDL_sysvideo.h"
#include "SDL_syswm.h"
Feb 9, 2020
Feb 9, 2020
30
#include "../../events/SDL_events_c.h"
31
32
33
34
35
36
37
38
39
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_keyboard_c.h"
#ifdef SDL_INPUT_LINUXEV
#include "../../core/linux/SDL_evdev.h"
#endif
/* KMS/DRM declarations */
#include "SDL_kmsdrmvideo.h"
Aug 22, 2017
Aug 22, 2017
40
#include "SDL_kmsdrmevents.h"
41
42
43
#include "SDL_kmsdrmopengles.h"
#include "SDL_kmsdrmmouse.h"
#include "SDL_kmsdrmdyn.h"
Oct 9, 2018
Oct 9, 2018
44
45
46
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
Feb 9, 2020
Feb 9, 2020
47
#include <poll.h>
Oct 9, 2018
Oct 9, 2018
49
#define KMSDRM_DRI_PATH "/dev/dri/"
Sep 6, 2020
Sep 6, 2020
51
52
#define AMDGPU_COMPAT 1
Jul 20, 2020
Jul 20, 2020
54
check_modesetting(int devindex)
Oct 9, 2018
Oct 9, 2018
56
57
SDL_bool available = SDL_FALSE;
char device[512];
Sep 26, 2020
Sep 26, 2020
58
unsigned int i;
Oct 9, 2018
Oct 9, 2018
59
60
61
int drm_fd;
SDL_snprintf(device, sizeof (device), "%scard%d", KMSDRM_DRI_PATH, devindex);
Jul 20, 2020
Jul 20, 2020
62
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "check_modesetting: probing \"%s\"", device);
Oct 9, 2018
Oct 9, 2018
64
drm_fd = open(device, O_RDWR | O_CLOEXEC);
65
66
67
if (drm_fd >= 0) {
if (SDL_KMSDRM_LoadSymbols()) {
drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd);
Feb 9, 2020
Feb 9, 2020
68
if (resources) {
Dec 1, 2018
Dec 1, 2018
69
70
71
72
73
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%scard%d connector, encoder and CRTC counts are: %d %d %d",
KMSDRM_DRI_PATH, devindex,
resources->count_connectors, resources->count_encoders, resources->count_crtcs);
if (resources->count_connectors > 0 && resources->count_encoders > 0 && resources->count_crtcs > 0) {
Sep 26, 2020
Sep 26, 2020
74
for (i = 0; i < resources->count_connectors; i++) {
Jul 20, 2020
Jul 20, 2020
75
76
77
78
79
80
81
82
83
84
85
drmModeConnector *conn = KMSDRM_drmModeGetConnector(drm_fd, resources->connectors[i]);
if (!conn) {
continue;
}
if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes) {
available = SDL_TRUE;
}
KMSDRM_drmModeFreeConnector(conn);
Jul 20, 2020
Jul 20, 2020
86
87
88
if (available) {
break;
}
Jul 20, 2020
Jul 20, 2020
89
}
Dec 1, 2018
Dec 1, 2018
90
}
91
92
93
94
95
96
97
98
99
100
KMSDRM_drmModeFreeResources(resources);
}
SDL_KMSDRM_UnloadSymbols();
}
close(drm_fd);
}
return available;
}
Aug 24, 2020
Aug 24, 2020
101
static unsigned int get_dricount(void)
Oct 9, 2018
Oct 9, 2018
102
{
Aug 24, 2020
Aug 24, 2020
103
unsigned int devcount = 0;
Oct 9, 2018
Oct 9, 2018
104
105
106
107
struct dirent *res;
struct stat sb;
DIR *folder;
Aug 23, 2020
Aug 23, 2020
108
109
110
if (!(stat(KMSDRM_DRI_PATH, &sb) == 0 && S_ISDIR(sb.st_mode))) {
SDL_SetError("The path %s cannot be opened or is not available",
KMSDRM_DRI_PATH);
Oct 9, 2018
Oct 9, 2018
111
112
113
114
return 0;
}
if (access(KMSDRM_DRI_PATH, F_OK) == -1) {
Aug 23, 2020
Aug 23, 2020
115
116
SDL_SetError("The path %s cannot be opened",
KMSDRM_DRI_PATH);
Oct 9, 2018
Oct 9, 2018
117
118
119
120
121
122
return 0;
}
folder = opendir(KMSDRM_DRI_PATH);
if (folder) {
while ((res = readdir(folder))) {
Aug 24, 2020
Aug 24, 2020
123
size_t len = SDL_strlen(res->d_name);
Jun 19, 2019
Jun 19, 2019
124
if (len > 4 && SDL_strncmp(res->d_name, "card", 4) == 0) {
Oct 9, 2018
Oct 9, 2018
125
126
127
128
129
130
131
132
133
134
135
136
devcount++;
}
}
closedir(folder);
}
return devcount;
}
static int
get_driindex(void)
{
Aug 24, 2020
Aug 24, 2020
137
138
const unsigned int devcount = get_dricount();
unsigned int i;
Oct 9, 2018
Oct 9, 2018
139
140
for (i = 0; i < devcount; i++) {
Jul 20, 2020
Jul 20, 2020
141
if (check_modesetting(i)) {
Oct 9, 2018
Oct 9, 2018
142
143
144
145
146
147
148
return i;
}
}
return -ENOENT;
}
Sep 7, 2020
Sep 7, 2020
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**********************/
/* DUMB BUFFER Block. */
/**********************/
/* Create a dumb buffer, mmap the dumb buffer and fill it with pixels, */
/* then create a KMS framebuffer wrapping the dumb buffer. */
static dumb_buffer *KMSDRM_CreateDumbBuffer(_THIS)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
struct drm_mode_create_dumb create;
struct drm_mode_map_dumb map;
struct drm_mode_destroy_dumb destroy;
Oct 22, 2020
Oct 22, 2020
164
dumb_buffer *ret = SDL_calloc(1, sizeof(*ret));
Oct 22, 2020
Oct 22, 2020
165
if (!ret) {
Oct 22, 2020
Oct 22, 2020
166
167
168
169
SDL_OutOfMemory();
return NULL;
}
Sep 7, 2020
Sep 7, 2020
170
171
172
173
174
175
176
177
178
179
180
181
/*
* The create ioctl uses the combination of depth and bpp to infer
* a format; 24/32 refers to DRM_FORMAT_XRGB8888 as defined in
* the drm_fourcc.h header. These arguments are the same as given
* to drmModeAddFB, which has since been superseded by
* drmModeAddFB2 as the latter takes an explicit format token.
*
* We only specify these arguments; the driver calculates the
* pitch (also known as stride or row length) and total buffer size
* for us, also returning us the GEM handle.
*/
create = (struct drm_mode_create_dumb) {
Oct 22, 2020
Oct 22, 2020
182
183
184
.width = dispdata->mode.hdisplay,
.height = dispdata->mode.vdisplay,
.bpp = 32,
Sep 7, 2020
Sep 7, 2020
185
186
187
};
if (KMSDRM_drmIoctl(viddata->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)) {
Oct 22, 2020
Oct 22, 2020
188
189
SDL_SetError("failed to create dumb buffer\n");
goto err;
Sep 7, 2020
Sep 7, 2020
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
}
ret->gem_handles[0] = create.handle;
ret->format = DRM_FORMAT_XRGB8888;
ret->modifier = DRM_FORMAT_MOD_LINEAR;
ret->width = create.width;
ret->height = create.height;
ret->pitches[0] = create.pitch;
/*
* In order to map the buffer, we call an ioctl specific to the buffer
* type, which returns us a fake offset to use with the mmap syscall.
* mmap itself then works as you expect.
*
* Note this means it is not possible to map arbitrary offsets of
* buffers without specifically requesting it from the kernel.
*/
map = (struct drm_mode_map_dumb) {
.handle = ret->gem_handles[0],
};
Oct 22, 2020
Oct 22, 2020
210
Sep 7, 2020
Sep 7, 2020
211
212
213
214
215
216
if (KMSDRM_drmIoctl(viddata->drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map)) {
SDL_SetError("failed to get mmap offset for the dumb buffer.");
goto err_dumb;
}
ret->dumb.mem = mmap(NULL, create.size, PROT_WRITE, MAP_SHARED,
Oct 22, 2020
Oct 22, 2020
217
218
viddata->drm_fd, map.offset);
Sep 7, 2020
Sep 7, 2020
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
if (ret->dumb.mem == MAP_FAILED) {
SDL_SetError("failed to get mmap offset for the dumb buffer.");
goto err_dumb;
}
ret->dumb.size = create.size;
return ret;
err_dumb:
destroy = (struct drm_mode_destroy_dumb) { .handle = create.handle };
KMSDRM_drmIoctl(viddata->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
err:
SDL_free(ret);
return NULL;
}
static void
KMSDRM_DestroyDumbBuffer(_THIS, dumb_buffer *buffer)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
struct drm_mode_destroy_dumb destroy = {
.handle = buffer->gem_handles[0],
};
KMSDRM_drmModeRmFB(viddata->drm_fd, buffer->fb_id);
munmap(buffer->dumb.mem, buffer->dumb.size);
KMSDRM_drmIoctl(viddata->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
free(buffer);
}
/* Using the CPU mapping, fill the dumb buffer with black pixels. */
static void
KMSDRM_FillDumbBuffer(dumb_buffer *buffer)
{
Sep 26, 2020
Sep 26, 2020
255
256
unsigned int x, y;
for (y = 0; y < buffer->height; y++) {
Oct 22, 2020
Oct 22, 2020
257
258
259
260
uint32_t *pix = (uint32_t *) ((uint8_t *) buffer->dumb.mem + (y * buffer->pitches[0]));
for (x = 0; x < buffer->width; x++) {
*pix++ = (0x00000000);
}
Sep 7, 2020
Sep 7, 2020
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
}
}
static dumb_buffer *KMSDRM_CreateBuffer(_THIS)
{
dumb_buffer *ret;
int err;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
ret = KMSDRM_CreateDumbBuffer(_this);
if (!ret)
return NULL;
/*
* Wrap our GEM buffer in a KMS framebuffer, so we can then attach it
* to a plane. Here's where we get out fb_id!
*/
err = KMSDRM_drmModeAddFB2(viddata->drm_fd, ret->width, ret->height,
ret->format, ret->gem_handles, ret->pitches,
ret->offsets, &ret->fb_id, 0);
if (err != 0 || ret->fb_id == 0) {
SDL_SetError("Failed AddFB2 on dumb buffer\n");
goto err;
}
return ret;
err:
KMSDRM_DestroyDumbBuffer(_this, ret);
return NULL;
}
/***************************/
/* DUMB BUFFER Block ends. */
/***************************/
Jul 28, 2020
Jul 28, 2020
299
300
301
302
303
304
/*********************************/
/* Atomic helper functions block */
/*********************************/
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
Sep 6, 2020
Sep 6, 2020
305
int add_connector_property(drmModeAtomicReq *req, struct connector *connector,
Aug 25, 2020
Aug 25, 2020
306
const char *name, uint64_t value)
Jul 28, 2020
Jul 28, 2020
307
{
Aug 23, 2020
Aug 23, 2020
308
309
unsigned int i;
int prop_id = 0;
Jul 28, 2020
Jul 28, 2020
310
Aug 23, 2020
Aug 23, 2020
311
for (i = 0 ; i < connector->props->count_props ; i++) {
Oct 22, 2020
Oct 22, 2020
312
313
314
315
if (strcmp(connector->props_info[i]->name, name) == 0) {
prop_id = connector->props_info[i]->prop_id;
break;
}
Aug 23, 2020
Aug 23, 2020
316
}
Jul 28, 2020
Jul 28, 2020
317
Aug 23, 2020
Aug 23, 2020
318
if (prop_id < 0) {
Oct 22, 2020
Oct 22, 2020
319
320
SDL_SetError("no connector property: %s", name);
return -EINVAL;
Aug 23, 2020
Aug 23, 2020
321
}
Jul 28, 2020
Jul 28, 2020
322
Aug 23, 2020
Aug 23, 2020
323
return KMSDRM_drmModeAtomicAddProperty(req, connector->connector->connector_id, prop_id, value);
Jul 28, 2020
Jul 28, 2020
324
325
}
Aug 25, 2020
Aug 25, 2020
326
327
int add_crtc_property(drmModeAtomicReq *req, struct crtc *crtc,
const char *name, uint64_t value)
Jul 28, 2020
Jul 28, 2020
328
{
Aug 23, 2020
Aug 23, 2020
329
330
unsigned int i;
int prop_id = -1;
Jul 28, 2020
Jul 28, 2020
331
Aug 23, 2020
Aug 23, 2020
332
for (i = 0 ; i < crtc->props->count_props ; i++) {
Oct 22, 2020
Oct 22, 2020
333
334
335
336
if (strcmp(crtc->props_info[i]->name, name) == 0) {
prop_id = crtc->props_info[i]->prop_id;
break;
}
Aug 23, 2020
Aug 23, 2020
337
}
Jul 28, 2020
Jul 28, 2020
338
Aug 23, 2020
Aug 23, 2020
339
if (prop_id < 0) {
Oct 22, 2020
Oct 22, 2020
340
341
SDL_SetError("no crtc property: %s", name);
return -EINVAL;
Aug 23, 2020
Aug 23, 2020
342
}
Jul 28, 2020
Jul 28, 2020
343
Aug 23, 2020
Aug 23, 2020
344
return KMSDRM_drmModeAtomicAddProperty(req, crtc->crtc->crtc_id, prop_id, value);
Jul 28, 2020
Jul 28, 2020
345
346
}
Aug 23, 2020
Aug 23, 2020
347
int add_plane_property(drmModeAtomicReq *req, struct plane *plane,
Aug 25, 2020
Aug 25, 2020
348
const char *name, uint64_t value)
Jul 28, 2020
Jul 28, 2020
349
{
Aug 8, 2020
Aug 8, 2020
350
351
unsigned int i;
int prop_id = -1;
Jul 28, 2020
Jul 28, 2020
352
Aug 17, 2020
Aug 17, 2020
353
for (i = 0 ; i < plane->props->count_props ; i++) {
Aug 23, 2020
Aug 23, 2020
354
if (strcmp(plane->props_info[i]->name, name) == 0) {
Oct 22, 2020
Oct 22, 2020
355
356
prop_id = plane->props_info[i]->prop_id;
break;
Aug 23, 2020
Aug 23, 2020
357
}
Aug 8, 2020
Aug 8, 2020
358
}
Jul 28, 2020
Jul 28, 2020
359
Aug 8, 2020
Aug 8, 2020
360
if (prop_id < 0) {
Aug 23, 2020
Aug 23, 2020
361
362
SDL_SetError("no plane property: %s", name);
return -EINVAL;
Aug 8, 2020
Aug 8, 2020
363
}
Jul 28, 2020
Jul 28, 2020
364
Aug 17, 2020
Aug 17, 2020
365
return KMSDRM_drmModeAtomicAddProperty(req, plane->plane->plane_id, prop_id, value);
Jul 28, 2020
Jul 28, 2020
366
367
}
Aug 5, 2020
Aug 5, 2020
368
369
#if 0
Jul 28, 2020
Jul 28, 2020
370
371
372
373
374
375
376
377
378
379
380
381
382
void print_plane_info(_THIS, drmModePlanePtr plane)
{
char *plane_type;
drmModeRes *resources;
uint32_t type = 0;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd,
plane->plane_id, DRM_MODE_OBJECT_PLANE);
/* Search the plane props for the plane type. */
for (int j = 0; j < props->count_props; j++) {
Oct 22, 2020
Oct 22, 2020
383
drmModePropertyPtr p = KMSDRM_drmModeGetProperty(viddata->drm_fd, props->props[j]);
Jul 28, 2020
Jul 28, 2020
384
Oct 22, 2020
Oct 22, 2020
385
386
387
if ((strcmp(p->name, "type") == 0)) {
type = props->prop_values[j];
}
Jul 28, 2020
Jul 28, 2020
388
Oct 22, 2020
Oct 22, 2020
389
KMSDRM_drmModeFreeProperty(p);
Jul 28, 2020
Jul 28, 2020
390
391
392
393
}
switch (type) {
case DRM_PLANE_TYPE_OVERLAY:
Oct 22, 2020
Oct 22, 2020
394
395
plane_type = "overlay";
break;
Jul 28, 2020
Jul 28, 2020
396
397
case DRM_PLANE_TYPE_PRIMARY:
Oct 22, 2020
Oct 22, 2020
398
399
plane_type = "primary";
break;
Jul 28, 2020
Jul 28, 2020
400
401
case DRM_PLANE_TYPE_CURSOR:
Oct 22, 2020
Oct 22, 2020
402
403
plane_type = "cursor";
break;
Jul 28, 2020
Jul 28, 2020
404
405
406
}
Aug 17, 2020
Aug 17, 2020
407
408
/* Remember that to present a plane on screen, it has to be
connected to a CRTC so the CRTC scans it,
Jul 28, 2020
Jul 28, 2020
409
410
411
412
413
414
415
416
417
scales it, etc... and presents it on screen. */
/* Now we look for the CRTCs supported by the plane. */
resources = KMSDRM_drmModeGetResources(viddata->drm_fd);
if (!resources)
return;
printf("--PLANE ID: %d\nPLANE TYPE: %s\nCRTC READING THIS PLANE: %d\nCRTCS SUPPORTED BY THIS PLANE: ", plane->plane_id, plane_type, plane->crtc_id);
for (int i = 0; i < resources->count_crtcs; i++) {
Oct 22, 2020
Oct 22, 2020
418
419
if (plane->possible_crtcs & (1 << i)) {
uint32_t crtc_id = resources->crtcs[i];
Jul 28, 2020
Jul 28, 2020
420
printf ("%d", crtc_id);
Oct 22, 2020
Oct 22, 2020
421
422
break;
}
Jul 28, 2020
Jul 28, 2020
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
}
printf ("\n\n");
}
void get_planes_info(_THIS)
{
drmModePlaneResPtr plane_resources;
uint32_t i;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
plane_resources = KMSDRM_drmModeGetPlaneResources(viddata->drm_fd);
if (!plane_resources) {
Oct 22, 2020
Oct 22, 2020
438
439
printf("drmModeGetPlaneResources failed: %s\n", strerror(errno));
return;
Jul 28, 2020
Jul 28, 2020
440
441
442
}
printf("--Number of planes found: %d-- \n", plane_resources->count_planes);
Aug 17, 2020
Aug 17, 2020
443
printf("--Usable CRTC that we have chosen: %d-- \n", dispdata->crtc->crtc->crtc_id);
Jul 28, 2020
Jul 28, 2020
444
445
446
447
448
449
/* Iterate on all the available planes. */
for (i = 0; (i < plane_resources->count_planes); i++) {
uint32_t plane_id = plane_resources->planes[i];
Oct 22, 2020
Oct 22, 2020
450
451
452
453
454
drmModePlanePtr plane = KMSDRM_drmModeGetPlane(viddata->drm_fd, plane_id);
if (!plane) {
printf("drmModeGetPlane(%u) failed: %s\n", plane_id, strerror(errno));
continue;
}
Jul 28, 2020
Jul 28, 2020
455
456
457
458
459
460
461
462
463
/* Print plane info. */
print_plane_info(_this, plane);
KMSDRM_drmModeFreePlane(plane);
}
KMSDRM_drmModeFreePlaneResources(plane_resources);
}
Aug 5, 2020
Aug 5, 2020
464
#endif
Jul 28, 2020
Jul 28, 2020
465
Aug 17, 2020
Aug 17, 2020
466
467
/* Get the plane_id of a plane that is of the specified plane type (primary,
overlay, cursor...) and can use the CRTC we have chosen previously. */
Aug 24, 2020
Aug 24, 2020
468
static int get_plane_id(_THIS, uint32_t plane_type)
Jul 28, 2020
Jul 28, 2020
469
{
Aug 23, 2020
Aug 23, 2020
470
471
drmModeRes *resources = NULL;
drmModePlaneResPtr plane_resources = NULL;
Jul 28, 2020
Jul 28, 2020
472
uint32_t i, j;
Aug 24, 2020
Aug 24, 2020
473
474
unsigned int crtc_index = 0;
int ret = -EINVAL;
Aug 17, 2020
Aug 17, 2020
475
int found = 0;
Jul 28, 2020
Jul 28, 2020
476
477
478
479
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
Aug 23, 2020
Aug 23, 2020
480
481
resources = KMSDRM_drmModeGetResources(viddata->drm_fd);
Aug 17, 2020
Aug 17, 2020
482
483
/* Get the crtc_index for the current CRTC.
It's needed to find out if a plane supports the CRTC. */
Aug 5, 2020
Aug 5, 2020
484
for (i = 0; i < resources->count_crtcs; i++) {
Oct 22, 2020
Oct 22, 2020
485
486
487
488
if (resources->crtcs[i] == dispdata->crtc->crtc->crtc_id) {
crtc_index = i;
break;
}
Aug 5, 2020
Aug 5, 2020
489
490
}
Jul 28, 2020
Jul 28, 2020
491
492
plane_resources = KMSDRM_drmModeGetPlaneResources(viddata->drm_fd);
if (!plane_resources) {
Oct 22, 2020
Oct 22, 2020
493
return SDL_SetError("drmModeGetPlaneResources failed.");
Jul 28, 2020
Jul 28, 2020
494
495
496
}
/* Iterate on all the available planes. */
Aug 17, 2020
Aug 17, 2020
497
for (i = 0; (i < plane_resources->count_planes) && !found; i++) {
Jul 28, 2020
Jul 28, 2020
498
Oct 22, 2020
Oct 22, 2020
499
uint32_t plane_id = plane_resources->planes[i];
Jul 28, 2020
Jul 28, 2020
500
Oct 22, 2020
Oct 22, 2020
501
502
503
504
drmModePlanePtr plane = KMSDRM_drmModeGetPlane(viddata->drm_fd, plane_id);
if (!plane) {
continue;
}
Jul 28, 2020
Jul 28, 2020
505
506
/* See if the current CRTC is available for this plane. */
Oct 22, 2020
Oct 22, 2020
507
if (plane->possible_crtcs & (1 << crtc_index)) {
Jul 28, 2020
Jul 28, 2020
508
Oct 22, 2020
Oct 22, 2020
509
510
511
drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(
viddata->drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
ret = plane_id;
Jul 28, 2020
Jul 28, 2020
512
Aug 17, 2020
Aug 17, 2020
513
514
/* Iterate on the plane props to find the type of the plane,
to see if it's of the type we want. */
Oct 22, 2020
Oct 22, 2020
515
for (j = 0; j < props->count_props; j++) {
Jul 28, 2020
Jul 28, 2020
516
Oct 22, 2020
Oct 22, 2020
517
518
drmModePropertyPtr p = KMSDRM_drmModeGetProperty(viddata->drm_fd,
props->props[j]);
Jul 28, 2020
Jul 28, 2020
519
Oct 22, 2020
Oct 22, 2020
520
521
522
523
if ((strcmp(p->name, "type") == 0) && (props->prop_values[j] == plane_type)) {
/* found our plane, use that: */
found = 1;
}
Jul 28, 2020
Jul 28, 2020
524
Aug 5, 2020
Aug 5, 2020
525
KMSDRM_drmModeFreeProperty(p);
Oct 22, 2020
Oct 22, 2020
526
}
Jul 28, 2020
Jul 28, 2020
527
Oct 22, 2020
Oct 22, 2020
528
529
KMSDRM_drmModeFreeObjectProperties(props);
}
Jul 28, 2020
Jul 28, 2020
530
Oct 22, 2020
Oct 22, 2020
531
KMSDRM_drmModeFreePlane(plane);
Jul 28, 2020
Jul 28, 2020
532
533
534
}
KMSDRM_drmModeFreePlaneResources(plane_resources);
Aug 23, 2020
Aug 23, 2020
535
KMSDRM_drmModeFreeResources(resources);
Jul 28, 2020
Jul 28, 2020
536
537
538
539
return ret;
}
Sep 7, 2020
Sep 7, 2020
540
/* Setup a plane and it's props. */
Aug 23, 2020
Aug 23, 2020
541
542
543
int
setup_plane(_THIS, struct plane **plane, uint32_t plane_type)
{
Aug 23, 2020
Aug 23, 2020
544
545
546
uint32_t plane_id;
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
Sep 13, 2020
Sep 13, 2020
547
*plane = SDL_calloc(1, sizeof(**plane));
Oct 22, 2020
Oct 22, 2020
548
549
550
if (!(*plane)) {
return SDL_OutOfMemory();
}
Aug 23, 2020
Aug 23, 2020
551
552
553
554
555
556
557
558
559
560
561
562
563
/* Get plane ID. */
plane_id = get_plane_id(_this, plane_type);
if (!plane_id) {
goto cleanup;
}
/* Get the DRM plane itself. */
(*plane)->plane = KMSDRM_drmModeGetPlane(viddata->drm_fd, plane_id);
/* Get the DRM plane properties. */
if ((*plane)->plane) {
Sep 26, 2020
Sep 26, 2020
564
unsigned int i;
Aug 23, 2020
Aug 23, 2020
565
(*plane)->props = KMSDRM_drmModeObjectGetProperties(viddata->drm_fd,
Oct 22, 2020
Oct 22, 2020
566
(*plane)->plane->plane_id, DRM_MODE_OBJECT_PLANE);
Aug 23, 2020
Aug 23, 2020
567
(*plane)->props_info = SDL_calloc((*plane)->props->count_props,
Sep 13, 2020
Sep 13, 2020
568
sizeof(*(*plane)->props_info));
Aug 23, 2020
Aug 23, 2020
569
Oct 22, 2020
Oct 22, 2020
570
571
572
573
574
if ( !((*plane)->props_info) ) {
SDL_OutOfMemory();
goto cleanup;
}
Sep 26, 2020
Sep 26, 2020
575
for (i = 0; i < (*plane)->props->count_props; i++) {
Aug 23, 2020
Aug 23, 2020
576
577
578
579
580
581
582
583
584
585
586
587
588
589
(*plane)->props_info[i] = KMSDRM_drmModeGetProperty(viddata->drm_fd,
(*plane)->props->props[i]);
}
}
return 0;
cleanup:
SDL_free(*plane);
*plane = NULL;
return -1;
}
/* Free a plane and it's props. */
Aug 23, 2020
Aug 23, 2020
590
591
592
void
free_plane(struct plane **plane)
{
Sep 8, 2020
Sep 8, 2020
593
if (*plane) {
Aug 23, 2020
Aug 23, 2020
594
595
596
597
598
599
600
601
602
603
604
605
606
if ((*plane)->plane) {
KMSDRM_drmModeFreePlane((*plane)->plane);
(*plane)->plane = NULL;
}
if ((*plane)->props_info) {
SDL_free((*plane)->props_info);
(*plane)->props_info = NULL;
}
SDL_free(*plane);
*plane = NULL;
}
}
Aug 17, 2020
Aug 17, 2020
607
608
609
/**********************************************************************************/
/* The most important ATOMIC fn of the backend. */
/* A PLANE reads a BUFFER, and a CRTC reads a PLANE and sends it's contents */
Sep 6, 2020
Sep 6, 2020
610
611
/* over to a CONNECTOR->ENCODER system (several CONNECTORS can be connected */
/* to the same PLANE). */
Aug 17, 2020
Aug 17, 2020
612
613
614
615
616
617
618
619
620
621
622
623
624
/* Think of a plane as a "frame" sorrounding a picture, where the "picture" */
/* is the buffer, and we move the "frame" from a picture to another, */
/* and the one that has the "frame" is the one sent over to the screen */
/* via the CONNECTOR->ENCODER system. */
/* Think of a PLANE as being "in the middle", it's the CENTRAL part */
/* bewteen the CRTC and the BUFFER that is shown on screen. */
/* What we do here is connect a PLANE to a CRTC and a BUFFER. */
/* -ALWAYS set the CRTC_ID and FB_ID attribs of a plane at the same time, */
/* meaning IN THE SAME atomic request. */
/* -And NEVER destroy a GBM surface whose buffers are being read by a plane: */
/* first, move the plane away from those buffers and ONLY THEN destroy the */
/* buffers and/or the GBM surface containig them. */
/**********************************************************************************/
Sep 12, 2020
Sep 12, 2020
625
void
Aug 23, 2020
Aug 23, 2020
626
drm_atomic_set_plane_props(struct KMSDRM_PlaneInfo *info)
Jul 28, 2020
Jul 28, 2020
627
628
{
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
Aug 8, 2020
Aug 8, 2020
629
630
631
632
/* Do we have a set of changes already in the making? If not, allocate a new one. */
if (!dispdata->atomic_req)
dispdata->atomic_req = KMSDRM_drmModeAtomicAlloc();
Aug 17, 2020
Aug 17, 2020
633
Sep 12, 2020
Sep 12, 2020
634
635
636
637
638
639
640
641
642
643
add_plane_property(dispdata->atomic_req, info->plane, "FB_ID", info->fb_id);
add_plane_property(dispdata->atomic_req, info->plane, "CRTC_ID", info->crtc_id);
add_plane_property(dispdata->atomic_req, info->plane, "SRC_W", info->src_w << 16);
add_plane_property(dispdata->atomic_req, info->plane, "SRC_H", info->src_h << 16);
add_plane_property(dispdata->atomic_req, info->plane, "SRC_X", info->src_x);
add_plane_property(dispdata->atomic_req, info->plane, "SRC_Y", info->src_y);
add_plane_property(dispdata->atomic_req, info->plane, "CRTC_W", info->crtc_w);
add_plane_property(dispdata->atomic_req, info->plane, "CRTC_H", info->crtc_h);
add_plane_property(dispdata->atomic_req, info->plane, "CRTC_X", info->crtc_x);
add_plane_property(dispdata->atomic_req, info->plane, "CRTC_Y", info->crtc_y);
Aug 8, 2020
Aug 8, 2020
644
645
646
647
648
649
650
}
int drm_atomic_commit(_THIS, SDL_bool blocking)
{
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
int ret;
Jul 28, 2020
Jul 28, 2020
651
Aug 8, 2020
Aug 8, 2020
652
653
if (!blocking)
dispdata->atomic_flags |= DRM_MODE_ATOMIC_NONBLOCK;
Jul 28, 2020
Jul 28, 2020
654
Aug 8, 2020
Aug 8, 2020
655
/* Never issue a new atomic commit if previous has not yet completed, or it will error. */
Aug 17, 2020
Aug 17, 2020
656
drm_atomic_waitpending(_this);
Jul 28, 2020
Jul 28, 2020
657
Aug 8, 2020
Aug 8, 2020
658
ret = KMSDRM_drmModeAtomicCommit(viddata->drm_fd, dispdata->atomic_req, dispdata->atomic_flags, NULL);
Aug 17, 2020
Aug 17, 2020
659
if (ret) {
Aug 23, 2020
Aug 23, 2020
660
661
SDL_SetError("Atomic commit failed, returned %d.", ret);
/* Uncomment this for fast-debugging */
Sep 12, 2020
Sep 12, 2020
662
// printf("ATOMIC COMMIT FAILED: %d.\n", ret);
Oct 22, 2020
Oct 22, 2020
663
goto out;
Aug 17, 2020
Aug 17, 2020
664
}
Jul 28, 2020
Jul 28, 2020
665
666
if (dispdata->kms_in_fence_fd != -1) {
Oct 22, 2020
Oct 22, 2020
667
668
close(dispdata->kms_in_fence_fd);
dispdata->kms_in_fence_fd = -1;
Jul 28, 2020
Jul 28, 2020
669
670
671
}
out:
Aug 8, 2020
Aug 8, 2020
672
673
674
KMSDRM_drmModeAtomicFree(dispdata->atomic_req);
dispdata->atomic_req = NULL;
dispdata->atomic_flags = 0;
Jul 28, 2020
Jul 28, 2020
675
676
677
678
return ret;
}
Aug 7, 2020
Aug 7, 2020
679
void
Aug 17, 2020
Aug 17, 2020
680
drm_atomic_waitpending(_THIS)
Aug 7, 2020
Aug 7, 2020
681
682
683
684
685
686
{
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
/* Will return immediately if we have already destroyed the fence, because we NULL-ify it just after.
Also, will return immediately in double-buffer mode, because kms_fence will alsawys be NULL. */
if (dispdata->kms_fence) {
Oct 22, 2020
Oct 22, 2020
687
EGLint status;
Aug 7, 2020
Aug 7, 2020
688
Oct 22, 2020
Oct 22, 2020
689
690
691
692
do {
status = _this->egl_data->eglClientWaitSyncKHR(_this->egl_data->egl_display,
dispdata->kms_fence, 0, EGL_FOREVER_KHR);
} while (status != EGL_CONDITION_SATISFIED_KHR);
Aug 7, 2020
Aug 7, 2020
693
Oct 22, 2020
Oct 22, 2020
694
695
_this->egl_data->eglDestroySyncKHR(_this->egl_data->egl_display, dispdata->kms_fence);
dispdata->kms_fence = NULL;
Aug 7, 2020
Aug 7, 2020
696
697
698
}
}
Jul 28, 2020
Jul 28, 2020
699
700
701
702
/***************************************/
/* End of Atomic helper functions block*/
/***************************************/
Oct 9, 2018
Oct 9, 2018
703
704
705
706
707
708
709
710
711
712
713
714
static int
KMSDRM_Available(void)
{
int ret = -ENOENT;
ret = get_driindex();
if (ret >= 0)
return 1;
return ret;
}
715
static void
Feb 9, 2020
Feb 9, 2020
716
KMSDRM_DeleteDevice(SDL_VideoDevice * device)
Feb 9, 2020
Feb 9, 2020
718
if (device->driverdata) {
719
720
721
SDL_free(device->driverdata);
device->driverdata = NULL;
}
Aug 2, 2017
Aug 2, 2017
722
723
SDL_free(device);
Feb 9, 2020
Feb 9, 2020
724
725
726
727
SDL_KMSDRM_UnloadSymbols();
}
Oct 15, 2020
Oct 15, 2020
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
static int
KMSDRM_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
{
int w, h;
uint32_t display_mm_width;
uint32_t display_mm_height;
SDL_DisplayData *dispdata;
dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); //viddata->devindex);
if (!dispdata) {
return SDL_SetError("No available displays");
}
display_mm_width = dispdata->connector->connector->mmWidth;
display_mm_height = dispdata->connector->connector->mmHeight;
w = dispdata->mode.hdisplay;
h = dispdata->mode.vdisplay;
*hdpi = display_mm_width ? (((float) w) * 25.4f / display_mm_width) : 0.0f;
*vdpi = display_mm_height ? (((float) h) * 25.4f / display_mm_height) : 0.0f;
*ddpi = SDL_ComputeDiagonalDPI(w, h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
return 0;
}
760
static SDL_VideoDevice *
Feb 9, 2020
Feb 9, 2020
761
KMSDRM_CreateDevice(int devindex)
762
763
{
SDL_VideoDevice *device;
Feb 9, 2020
Feb 9, 2020
764
SDL_VideoData *viddata;
Jul 12, 2020
Jul 12, 2020
766
767
768
769
if (!KMSDRM_Available()) {
return NULL;
}
Oct 9, 2018
Oct 9, 2018
770
771
772
773
774
if (!devindex || (devindex > 99)) {
devindex = get_driindex();
}
if (devindex < 0) {
Aug 17, 2020
Aug 17, 2020
775
SDL_SetError("devindex (%d) must be between 0 and 99.", devindex);
776
777
778
779
780
781
782
783
return NULL;
}
if (!SDL_KMSDRM_LoadSymbols()) {
return NULL;
}
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
Feb 9, 2020
Feb 9, 2020
784
if (!device) {
785
SDL_OutOfMemory();
Aug 2, 2017
Aug 2, 2017
786
return NULL;
Feb 9, 2020
Feb 9, 2020
789
790
viddata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
if (!viddata) {
791
792
793
SDL_OutOfMemory();
goto cleanup;
}
Feb 9, 2020
Feb 9, 2020
794
795
viddata->devindex = devindex;
viddata->drm_fd = -1;
Feb 9, 2020
Feb 9, 2020
797
device->driverdata = viddata;
May 26, 2020
May 26, 2020
799
/* Setup all functions that can be handled from this backend. */
800
801
802
device->VideoInit = KMSDRM_VideoInit;
device->VideoQuit = KMSDRM_VideoQuit;
device->GetDisplayModes = KMSDRM_GetDisplayModes;
Sep 11, 2020
Sep 11, 2020
803
device->SetDisplayMode = KMSDRM_SetDisplayMode;
Oct 15, 2020
Oct 15, 2020
804
device->GetDisplayDPI = KMSDRM_GetDisplayDPI;
Aug 28, 2017
Aug 28, 2017
805
806
device->CreateSDLWindow = KMSDRM_CreateWindow;
device->CreateSDLWindowFrom = KMSDRM_CreateWindowFrom;
807
808
809
810
device->SetWindowTitle = KMSDRM_SetWindowTitle;
device->SetWindowIcon = KMSDRM_SetWindowIcon;
device->SetWindowPosition = KMSDRM_SetWindowPosition;
device->SetWindowSize = KMSDRM_SetWindowSize;
Aug 28, 2020
Aug 28, 2020
811
device->SetWindowFullscreen = KMSDRM_SetWindowFullscreen;
812
813
814
815
816
817
818
819
820
device->ShowWindow = KMSDRM_ShowWindow;
device->HideWindow = KMSDRM_HideWindow;
device->RaiseWindow = KMSDRM_RaiseWindow;
device->MaximizeWindow = KMSDRM_MaximizeWindow;
device->MinimizeWindow = KMSDRM_MinimizeWindow;
device->RestoreWindow = KMSDRM_RestoreWindow;
device->SetWindowGrab = KMSDRM_SetWindowGrab;
device->DestroyWindow = KMSDRM_DestroyWindow;
device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo;
Aug 4, 2017
Aug 4, 2017
821
#if SDL_VIDEO_OPENGL_EGL
Sep 10, 2020
Sep 10, 2020
822
device->GL_DefaultProfileConfig = KMSDRM_GLES_DefaultProfileConfig;
823
824
device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary;
device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress;
Sep 6, 2020
Sep 6, 2020
825
device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary;
826
827
828
829
device->GL_CreateContext = KMSDRM_GLES_CreateContext;
device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
Sep 10, 2020
Sep 10, 2020
830
device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
831
device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
Aug 4, 2017
Aug 4, 2017
832
#endif
833
device->PumpEvents = KMSDRM_PumpEvents;
Feb 9, 2020
Feb 9, 2020
834
device->free = KMSDRM_DeleteDevice;
835
836
837
838
return device;
cleanup:
Feb 9, 2020
Feb 9, 2020
839
if (device)
840
SDL_free(device);
Feb 9, 2020
Feb 9, 2020
841
842
if (viddata)
SDL_free(viddata);
843
844
845
846
847
848
return NULL;
}
VideoBootStrap KMSDRM_bootstrap = {
"KMSDRM",
"KMS/DRM Video Driver",
Feb 9, 2020
Feb 9, 2020
849
KMSDRM_CreateDevice
850
851
852
853
854
855
856
857
};
static void
KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
{
KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data;
Mar 13, 2019
Mar 13, 2019
858
if (fb_info && fb_info->drm_fd >= 0 && fb_info->fb_id != 0) {
859
860
861
862
KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id);
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id);
}
Mar 11, 2019
Mar 11, 2019
863
SDL_free(fb_info);
864
865
866
867
868
}
KMSDRM_FBInfo *
KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
{
Feb 9, 2020
Feb 9, 2020
869
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
Aug 17, 2020
Aug 17, 2020
870
871
872
unsigned width, height;
uint32_t format, strides[4] = {0}, handles[4] = {0}, offsets[4] = {0};
const int num_planes = KMSDRM_gbm_bo_get_plane_count(bo);
Sep 26, 2020
Sep 26, 2020
873
unsigned int i;
Feb 15, 2020
Feb 15, 2020
874
int ret;
Feb 9, 2020
Feb 9, 2020
875
876
877
878
879
/* Check for an existing framebuffer */
KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo);
if (fb_info) {
880
881
882
return fb_info;
}
Aug 17, 2020
Aug 17, 2020
883
884
/* Create a structure that contains the info about framebuffer
that we need to use it. */
885
fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo));
Feb 9, 2020
Feb 9, 2020
886
if (!fb_info) {
Aug 5, 2017
Aug 5, 2017
887
888
889
SDL_OutOfMemory();
return NULL;
}
Feb 9, 2020
Feb 9, 2020
891
fb_info->drm_fd = viddata->drm_fd;
Aug 17, 2020
Aug 17, 2020
893
894
895
896
width = KMSDRM_gbm_bo_get_width(bo);
height = KMSDRM_gbm_bo_get_height(bo);
format = KMSDRM_gbm_bo_get_format(bo);
Sep 26, 2020
Sep 26, 2020
897
for (i = 0; i < num_planes; i++) {
Oct 22, 2020
Oct 22, 2020
898
899
900
strides[i] = KMSDRM_gbm_bo_get_stride_for_plane(bo, i);
handles[i] = KMSDRM_gbm_bo_get_handle(bo).u32;
offsets[i] = KMSDRM_gbm_bo_get_offset(bo, i);
Aug 17, 2020
Aug 17, 2020
901
902
903
904
905
906
}
/* Create framebuffer object for the buffer.
It's VERY important to note that fb_id is what we ise to set the FB_ID prop of a plane
when using the ATOMIC interface, and we get fb_id it here. */
ret = KMSDRM_drmModeAddFB2(viddata->drm_fd, width, height, format,
Oct 22, 2020
Oct 22, 2020
907
handles, strides, offsets, &fb_info->fb_id, 0);
Aug 17, 2020
Aug 17, 2020
908
Feb 9, 2020
Feb 9, 2020
909
910
911
if (ret) {
SDL_free(fb_info);
return NULL;
Feb 9, 2020
Feb 9, 2020
913
Aug 17, 2020
Aug 17, 2020
914
915
916
/* Set the userdata pointer. This pointer is used to store custom data that we need
to access in the future, so we store the fb_id here for later use, because fb_id is
what we need to set the FB_ID property of a plane when using the ATOMIC interface. */
917
KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback);
Feb 9, 2020
Feb 9, 2020
918
919
920
921
922
923
924
925
return fb_info;
}
/*****************************************************************************/
/* SDL Video and Display initialization/handling functions */
/* _this is a SDL_VideoDevice * */
/*****************************************************************************/
Aug 17, 2020
Aug 17, 2020
926
Sep 6, 2020
Sep 6, 2020
927
928
929
930
/* Destroy the window surfaces and buffers. Have the PRIMARY PLANE
disconnected from these buffers before doing so, or have the PRIMARY PLANE
reading the original FB where the TTY lives, before doing this, or CRTC will
be disconnected by the kernel. */
Aug 25, 2020
Aug 25, 2020
931
void
Sep 6, 2020
Sep 6, 2020
932
KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
Aug 25, 2020
Aug 25, 2020
933
{
Sep 6, 2020
Sep 6, 2020
934
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
Sep 6, 2020
Sep 6, 2020
935
936
937
938
939
940
941
942
943
944
945
946
947
948
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
KMSDRM_PlaneInfo plane_info = {0};
#if SDL_VIDEO_OPENGL_EGL
EGLContext egl_context;
#endif
/********************************************************************/
/* BLOCK 1: protect the PRIMARY PLANE before destroying the buffers */
/* it's using. */
/********************************************************************/
plane_info.plane = dispdata->display_plane;
plane_info.crtc_id = dispdata->crtc->crtc->crtc_id;
Sep 7, 2020
Sep 7, 2020
949
plane_info.fb_id = dispdata->dumb_buffer->fb_id;
Sep 6, 2020
Sep 6, 2020
950
951
952
953
954
955
956
957
958
plane_info.src_w = dispdata->mode.hdisplay;
plane_info.src_h = dispdata->mode.vdisplay;
plane_info.crtc_w = dispdata->mode.hdisplay;
plane_info.crtc_h = dispdata->mode.vdisplay;
drm_atomic_set_plane_props(&plane_info);
/* Issue blocking atomic commit. */
if (drm_atomic_commit(_this, SDL_TRUE)) {
Sep 12, 2020
Sep 12, 2020
959
SDL_SetError("Failed to issue atomic commit on window destruction.");
Sep 6, 2020
Sep 6, 2020
960
961
962
963
964
965
966
}
/****************************************************************************/
/* BLOCK 2: We can finally destroy the window GBM and EGL surfaces, and */
/* GBM buffers now that the buffers are not being used by the PRIMARY PLANE */
/* anymore. */
/****************************************************************************/
Aug 7, 2020
Aug 7, 2020
967
Sep 6, 2020
Sep 6, 2020
968
969
970
971
/* Destroy the GBM surface and buffers. */
if (windata->bo) {
KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo);
windata->bo = NULL;
Feb 9, 2020
Feb 9, 2020
972
973
}
Sep 6, 2020
Sep 6, 2020
974
if (windata->next_bo) {
Oct 22, 2020
Oct 22, 2020
975
976
KMSDRM_gbm_surface_release_buffer(windata->gs, windata->next_bo);
windata->next_bo = NULL;
Feb 9, 2020
Feb 9, 2020
977
978
}
Sep 6, 2020
Sep 6, 2020
979
980
/* Destroy the EGL surface. */
#if SDL_VIDEO_OPENGL_EGL
Sep 6, 2020
Sep 6, 2020
981
982
983
984
985
986
987
988
989
990
991
/***************************************************************************/
/* In this eglMakeCurrent() call, we disable the current EGL surface */
/* because we're going to destroy it, but DON'T disable the EGL context, */
/* because it won't be enabled again until the programs ask for a pageflip */
/* so we get to SwapWindow(). */
/* If we disable the context until then and a program tries to retrieve */
/* the context version info before calling for a pageflip, the program */
/* will get wrong info and we will be in trouble. */
/***************************************************************************/
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, egl_context);
Feb 9, 2020
Feb 9, 2020
992
Sep 6, 2020
Sep 6, 2020
993
994
995
996
997
998
999
if (windata->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, windata->egl_surface);
windata->egl_surface = EGL_NO_SURFACE;
}
#endif
if (windata->gs) {
Oct 22, 2020
Oct 22, 2020
1000
KMSDRM_gbm_surface_destroy(windata->gs);