@@ -67,6 +67,23 @@ void KMSDRM_DestroyCursorBO(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
67
67
68
68
// Destroy the curso GBM BO.
69
69
if (dispdata -> cursor_bo ) {
70
+ SDL_VideoData * viddata = (SDL_VideoData * ) _this -> internal ;
71
+ if (viddata -> is_atomic ) {
72
+ if (dispdata -> cursor_plane ) {
73
+ // Unset the the cursor BO from the cursor plane.
74
+ KMSDRM_PlaneInfo info ;
75
+ SDL_zero (info );
76
+ info .plane = dispdata -> cursor_plane ;
77
+ drm_atomic_set_plane_props (& info );
78
+ // Wait until the cursor is unset from the cursor plane before destroying it's BO.
79
+ if (drm_atomic_commit (_this , true, false)) {
80
+ SDL_SetError ("Failed atomic commit in KMSDRM_DenitMouse." );
81
+ }
82
+ // Free the cursor plane, on which the cursor was being shown.
83
+ free_plane (& dispdata -> cursor_plane );
84
+ }
85
+ }
86
+
70
87
KMSDRM_gbm_bo_destroy (dispdata -> cursor_bo );
71
88
dispdata -> cursor_bo = NULL ;
72
89
dispdata -> cursor_bo_drm_fd = -1 ;
@@ -78,11 +95,14 @@ void KMSDRM_DestroyCursorBO(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
78
95
build a window and assign a display to it. */
79
96
bool KMSDRM_CreateCursorBO (SDL_VideoDisplay * display )
80
97
{
81
-
82
98
SDL_VideoDevice * dev = SDL_GetVideoDevice ();
83
99
SDL_VideoData * viddata = dev -> internal ;
84
100
SDL_DisplayData * dispdata = display -> internal ;
85
101
102
+ if (viddata -> is_atomic ) {
103
+ setup_plane (dev , & dispdata -> cursor_plane , DRM_PLANE_TYPE_CURSOR );
104
+ }
105
+
86
106
if (!KMSDRM_gbm_device_is_format_supported (viddata -> gbm_dev ,
87
107
GBM_FORMAT_ARGB8888 ,
88
108
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE )) {
@@ -121,15 +141,29 @@ static bool KMSDRM_RemoveCursorFromBO(SDL_VideoDisplay *display)
121
141
SDL_VideoDevice * video_device = SDL_GetVideoDevice ();
122
142
SDL_VideoData * viddata = video_device -> internal ;
123
143
124
- const int rc = KMSDRM_drmModeSetCursor (viddata -> drm_fd , dispdata -> crtc -> crtc_id , 0 , 0 , 0 );
125
- if (rc < 0 ) {
126
- result = SDL_SetError ("drmModeSetCursor() failed: %s" , strerror (- rc ));
144
+ if (viddata -> is_atomic ) {
145
+ if (dispdata -> cursor_plane ) {
146
+ KMSDRM_PlaneInfo info ;
147
+ SDL_zero (info );
148
+ info .plane = dispdata -> cursor_plane ;
149
+ // The rest of the members are zeroed, so this takes away the cursor from the cursor plane.
150
+ drm_atomic_set_plane_props (& info );
151
+ if (drm_atomic_commit (video_device , true, false)) {
152
+ result = SDL_SetError ("Failed atomic commit in KMSDRM_ShowCursor." );
153
+ }
154
+ }
155
+ } else {
156
+ const int rc = KMSDRM_drmModeSetCursor (viddata -> drm_fd , dispdata -> crtc .crtc -> crtc_id , 0 , 0 , 0 );
157
+ if (rc < 0 ) {
158
+ result = SDL_SetError ("drmModeSetCursor() failed: %s" , strerror (- rc ));
159
+ }
127
160
}
161
+
128
162
return result ;
129
163
}
130
164
131
165
// Dump a cursor buffer to a display's DRM cursor BO.
132
- static bool KMSDRM_DumpCursorToBO (SDL_VideoDisplay * display , SDL_Cursor * cursor )
166
+ static bool KMSDRM_DumpCursorToBO (SDL_VideoDisplay * display , SDL_Mouse * mouse , SDL_Cursor * cursor )
133
167
{
134
168
SDL_DisplayData * dispdata = display -> internal ;
135
169
SDL_CursorData * curdata = cursor -> internal ;
@@ -173,22 +207,42 @@ static bool KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor)
173
207
goto cleanup ;
174
208
}
175
209
176
- // Put the GBM BO buffer on screen using the DRM interface.
177
- bo_handle = KMSDRM_gbm_bo_get_handle (dispdata -> cursor_bo ).u32 ;
178
- if (curdata -> hot_x == 0 && curdata -> hot_y == 0 ) {
179
- rc = KMSDRM_drmModeSetCursor (viddata -> drm_fd , dispdata -> crtc -> crtc_id ,
180
- bo_handle , dispdata -> cursor_w , dispdata -> cursor_h );
210
+ if (viddata -> is_atomic ) {
211
+ // Get the fb_id for the GBM BO so we can show it on the cursor plane.
212
+ KMSDRM_FBInfo * fb = KMSDRM_FBFromBO (video_device , dispdata -> cursor_bo );
213
+ KMSDRM_PlaneInfo info ;
214
+
215
+ // Show the GBM BO buffer on the cursor plane.
216
+ SDL_zero (info );
217
+ info .plane = dispdata -> cursor_plane ;
218
+ info .crtc_id = dispdata -> crtc .crtc -> crtc_id ;
219
+ info .fb_id = fb -> fb_id ;
220
+ info .src_w = dispdata -> cursor_w ;
221
+ info .src_h = dispdata -> cursor_h ;
222
+ info .crtc_x = ((int32_t ) SDL_roundf (mouse -> x )) - curdata -> hot_x ;
223
+ info .crtc_y = ((int32_t ) SDL_roundf (mouse -> y )) - curdata -> hot_y ;
224
+ info .crtc_w = curdata -> w ;
225
+ info .crtc_h = curdata -> h ;
226
+ drm_atomic_set_plane_props (& info );
227
+ if (drm_atomic_commit (video_device , true, false)) {
228
+ result = SDL_SetError ("Failed atomic commit in KMSDRM_ShowCursor." );
229
+ goto cleanup ;
230
+ }
181
231
} else {
182
- rc = KMSDRM_drmModeSetCursor2 (viddata -> drm_fd , dispdata -> crtc -> crtc_id ,
183
- bo_handle , dispdata -> cursor_w , dispdata -> cursor_h , curdata -> hot_x , curdata -> hot_y );
184
- }
185
- if (rc < 0 ) {
186
- result = SDL_SetError ("Failed to set DRM cursor: %s" , strerror (- rc ));
187
- goto cleanup ;
232
+ // Put the GBM BO buffer on screen using the DRM interface.
233
+ bo_handle = KMSDRM_gbm_bo_get_handle (dispdata -> cursor_bo ).u32 ;
234
+ if (curdata -> hot_x == 0 && curdata -> hot_y == 0 ) {
235
+ rc = KMSDRM_drmModeSetCursor (viddata -> drm_fd , dispdata -> crtc .crtc -> crtc_id , bo_handle , dispdata -> cursor_w , dispdata -> cursor_h );
236
+ } else {
237
+ rc = KMSDRM_drmModeSetCursor2 (viddata -> drm_fd , dispdata -> crtc .crtc -> crtc_id , bo_handle , dispdata -> cursor_w , dispdata -> cursor_h , curdata -> hot_x , curdata -> hot_y );
238
+ }
239
+ if (rc < 0 ) {
240
+ result = SDL_SetError ("Failed to set DRM cursor: %s" , strerror (- rc ));
241
+ goto cleanup ;
242
+ }
188
243
}
189
244
190
245
cleanup :
191
-
192
246
if (ready_buffer ) {
193
247
SDL_free (ready_buffer );
194
248
}
@@ -316,7 +370,7 @@ static bool KMSDRM_ShowCursor(SDL_Cursor *cursor)
316
370
if (cursor ) {
317
371
/* Dump the cursor to the display DRM cursor BO so it becomes visible
318
372
on that display. */
319
- result = KMSDRM_DumpCursorToBO (display , cursor );
373
+ result = KMSDRM_DumpCursorToBO (display , mouse , cursor );
320
374
} else {
321
375
// Hide the cursor on that display.
322
376
result = KMSDRM_RemoveCursorFromBO (display );
@@ -327,6 +381,19 @@ static bool KMSDRM_ShowCursor(SDL_Cursor *cursor)
327
381
return result ;
328
382
}
329
383
384
+ static void drm_atomic_movecursor (const SDL_CursorData * curdata , uint16_t x , uint16_t y )
385
+ {
386
+ SDL_DisplayData * dispdata = (SDL_DisplayData * )SDL_GetDisplayDriverData (0 );
387
+ if (dispdata -> cursor_plane ) { // We can't move a non-existing cursor, but that's ok.
388
+ // Do we have a set of changes already in the making? If not, allocate a new one.
389
+ if (!dispdata -> atomic_req ) {
390
+ dispdata -> atomic_req = KMSDRM_drmModeAtomicAlloc ();
391
+ }
392
+ add_plane_property (dispdata -> atomic_req , dispdata -> cursor_plane , "CRTC_X" , x - curdata -> hot_x );
393
+ add_plane_property (dispdata -> atomic_req , dispdata -> cursor_plane , "CRTC_Y" , y - curdata -> hot_y );
394
+ }
395
+ }
396
+
330
397
static bool KMSDRM_WarpMouseGlobal (float x , float y )
331
398
{
332
399
SDL_Mouse * mouse = SDL_GetMouse ();
@@ -340,17 +407,25 @@ static bool KMSDRM_WarpMouseGlobal(float x, float y)
340
407
341
408
// And now update the cursor graphic position on screen.
342
409
if (dispdata -> cursor_bo ) {
343
- const int rc = KMSDRM_drmModeMoveCursor (dispdata -> cursor_bo_drm_fd , dispdata -> crtc -> crtc_id , (int )x , (int )y );
344
- if (rc < 0 ) {
345
- return SDL_SetError ("drmModeMoveCursor() failed: %s" , strerror (- rc ));
410
+ SDL_VideoDevice * dev = SDL_GetVideoDevice ();
411
+ SDL_VideoData * viddata = dev -> internal ;
412
+ if (viddata -> is_atomic ) {
413
+ const SDL_CursorData * curdata = (const SDL_CursorData * ) mouse -> cur_cursor -> internal ;
414
+ drm_atomic_movecursor (curdata , (uint16_t ) (int ) x , (uint16_t ) (int ) y );
415
+ } else {
416
+ const int rc = KMSDRM_drmModeMoveCursor (dispdata -> cursor_bo_drm_fd , dispdata -> crtc .crtc -> crtc_id , (int )x , (int )y );
417
+ if (rc < 0 ) {
418
+ return SDL_SetError ("drmModeMoveCursor() failed: %s" , strerror (- rc ));
419
+ }
346
420
}
347
- return true;
348
421
} else {
349
422
return SDL_SetError ("Cursor not initialized properly." );
350
423
}
351
424
} else {
352
425
return SDL_SetError ("No mouse or current cursor." );
353
426
}
427
+
428
+ return true;
354
429
}
355
430
356
431
static bool KMSDRM_WarpMouse (SDL_Window * window , float x , float y )
@@ -394,14 +469,27 @@ static bool KMSDRM_MoveCursor(SDL_Cursor *cursor)
394
469
if (mouse && mouse -> cur_cursor && mouse -> focus ) {
395
470
SDL_Window * window = mouse -> focus ;
396
471
SDL_DisplayData * dispdata = SDL_GetDisplayDriverDataForWindow (window );
472
+ SDL_VideoDevice * dev = SDL_GetVideoDevice ();
473
+ SDL_VideoData * viddata = dev -> internal ;
397
474
398
475
if (!dispdata -> cursor_bo ) {
399
476
return SDL_SetError ("Cursor not initialized properly." );
400
477
}
401
478
402
- const int rc = KMSDRM_drmModeMoveCursor (dispdata -> cursor_bo_drm_fd , dispdata -> crtc -> crtc_id , (int )mouse -> x , (int )mouse -> y );
403
- if (rc < 0 ) {
404
- return SDL_SetError ("drmModeMoveCursor() failed: %s" , strerror (- rc ));
479
+ if (viddata -> is_atomic ) {
480
+ /* !!! FIXME: Some programs expect cursor movement even while they don't do SwapWindow() calls,
481
+ and since we ride on the atomic_commit() in SwapWindow() for cursor movement,
482
+ cursor won't move in these situations. We could do an atomic_commit() here
483
+ for each cursor movement request, but it cripples the movement to 30FPS,
484
+ so a future solution is needed. SDLPoP "QUIT?" menu is an example of this
485
+ situation. */
486
+ const SDL_CursorData * curdata = (const SDL_CursorData * ) mouse -> cur_cursor -> internal ;
487
+ drm_atomic_movecursor (curdata , (uint16_t ) (int ) mouse -> x , (uint16_t ) (int ) mouse -> y );
488
+ } else {
489
+ const int rc = KMSDRM_drmModeMoveCursor (dispdata -> cursor_bo_drm_fd , dispdata -> crtc .crtc -> crtc_id , (int )mouse -> x , (int )mouse -> y );
490
+ if (rc < 0 ) {
491
+ return SDL_SetError ("drmModeMoveCursor() failed: %s" , strerror (- rc ));
492
+ }
405
493
}
406
494
}
407
495
return true;
0 commit comments