[KMS/DRM] Prevent creating another default cursor everytime a window is created. Other fixes and cleanups.
diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c
index a8b7a04..1546c7c 100644
--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c
+++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c
@@ -40,6 +40,21 @@
static void KMSDRM_WarpMouse(SDL_Window * window, int x, int y);
static int KMSDRM_WarpMouseGlobal(int x, int y);
+/**************************************************************************************/
+/* BEFORE CODING ANYTHING MOUSE/CURSOR RELATED, REMEMBER THIS. */
+/* How does SDL manage cursors internally? First, mouse =! cursor. The mouse can have */
+/* many cursors in mouse->cursors. */
+/* -SDL tells us to create a cursor with KMSDRM_CreateCursor(). It can create many */
+/* cursosr with this, not only one. */
+/* -SDL stores those cursors in a cursors array, in mouse->cursors. */
+/* -Whenever it wants (or the programmer wants) takes a cursor from that array */
+/* and shows it on screen with KMSDRM_ShowCursor(). */
+/* KMSDRM_ShowCursor() simply shows or hides the cursor it receives: it does NOT */
+/* mind if it's mouse->cur_cursor, etc. */
+/* -If KMSDRM_ShowCursor() returns succesfully, that cursor becomes mouse->cur_cursor */
+/* and mouse->cursor_shown is 1. */
+/**************************************************************************************/
+
/**********************************/
/* Atomic helper functions block. */
/**********************************/
@@ -98,8 +113,9 @@
return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
}
-/* This simply gets the cursor soft-buffer ready. We don't copy it to a GBO BO until ShowCursor()
- because the cusor GBM BO (living in dispata) is destroyed and recreated when we recreate windows, etc. */
+/* This simply gets the cursor soft-buffer ready. We don't copy it to a GBO BO
+ until ShowCursor() because the cusor GBM BO (living in dispata) is destroyed
+ and recreated when we recreate windows, etc. */
static SDL_Cursor *
KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
{
@@ -204,20 +220,16 @@
KMSDRM_ShowCursor(mouse->cur_cursor);
}
-/* Show the specified cursor, or hide if cursor is NULL.
- cur_cursor is the current cursor, and cursor is the new cursor.
- A cursor is displayed on a display, so we have to add a pointer to dispdata
- to the driverdata
- */
+/* Show the specified cursor, or hide if cursor is NULL or has no focus. */
static int
KMSDRM_ShowCursor(SDL_Cursor * cursor)
{
SDL_VideoDevice *video_device = SDL_GetVideoDevice();
- //SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
+ //SDL_VideoData *viddata = ((SDL_VideoData *)video_device->driverdata);
+ SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
SDL_Mouse *mouse;
KMSDRM_CursorData *curdata;
- SDL_VideoDisplay *display = NULL;
- SDL_DisplayData *dispdata = NULL;
+
KMSDRM_FBInfo *fb;
KMSDRM_PlaneInfo info = {0};
@@ -234,41 +246,28 @@
return SDL_SetError("No mouse.");
}
- if (mouse->focus) {
- display = SDL_GetDisplayForWindow(mouse->focus);
- if (display) {
- dispdata = (SDL_DisplayData*) display->driverdata;
+ /*********************************************************/
+ /* Hide cursor if it's NULL or it has no focus(=winwow). */
+ /*********************************************************/
+ if (!cursor || !mouse->focus) {
+ if (dispdata->cursor_plane) {
+ /* Hide the drm cursor with no more considerations because
+ SDL_VideoQuit() takes us here after disabling the mouse
+ so there is no mouse->cur_cursor by now. */
+ info.plane = dispdata->cursor_plane;
+ /* The rest of the members are zeroed, so this takes away the cursor
+ from the cursor plane. */
+ drm_atomic_set_plane_props(&info);
+ if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
+ ret = SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
+ }
}
- }
-
- /**********************************/
- /* if cursor == NULL, HIDE cursor */
- /**********************************/
- if (!cursor) {
- /* Hide CURRENT cursor, a cursor that is already on screen
- and SDL is stored in mouse->cur_cursor. */
- if (mouse->cur_cursor && mouse->cur_cursor->driverdata) {
- if (dispdata && dispdata->cursor_plane) {
- info.plane = dispdata->cursor_plane;
- /* The rest of the members are zeroed. */
- drm_atomic_set_plane_props(&info);
- if (drm_atomic_commit(display->device, SDL_TRUE, SDL_FALSE))
- return SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
- }
- return 0;
- }
- return SDL_SetError("Couldn't find cursor to hide.");
+ return ret;
}
/************************************************/
/* If cursor != NULL, DO show cursor on display */
/************************************************/
- if (!display) {
- return SDL_SetError("Could not get display for mouse.");
- }
- if (!dispdata) {
- return SDL_SetError("Could not get display driverdata.");
- }
if (!dispdata->cursor_plane) {
return SDL_SetError("Hardware cursor plane not initialized.");
}
@@ -279,7 +278,8 @@
return SDL_SetError("Cursor not initialized properly.");
}
- /* Prepare a buffer we can dump to our GBM BO (different size, alpha premultiplication...) */
+ /* Prepare a buffer we can dump to our GBM BO (different
+ size, alpha premultiplication...) */
bo_stride = KMSDRM_gbm_bo_get_stride(dispdata->cursor_bo);
bufsize = bo_stride * curdata->h;
@@ -315,8 +315,8 @@
info.plane = dispdata->cursor_plane;
info.crtc_id = dispdata->crtc->crtc->crtc_id;
info.fb_id = fb->fb_id;
- info.src_w = curdata->w;
- info.src_h = curdata->h;
+ info.src_w = dispdata->cursor_w;
+ info.src_h = dispdata->cursor_h;
info.crtc_x = mouse->x - curdata->hot_x;
info.crtc_y = mouse->y - curdata->hot_y;
info.crtc_w = curdata->w;
@@ -324,7 +324,7 @@
drm_atomic_set_plane_props(&info);
- if (drm_atomic_commit(display->device, SDL_TRUE, SDL_FALSE)) {
+ if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
ret = SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
goto cleanup;
}
@@ -339,8 +339,7 @@
return ret;
}
-/* We have destroyed the cursor by now, in KMSDRM_DestroyCursor.
- This is only for freeing the SDL_cursor.*/
+/* This is only for freeing the SDL_cursor.*/
static void
KMSDRM_FreeCursor(SDL_Cursor * cursor)
{
@@ -398,13 +397,40 @@
return 0;
}
+/* UNDO WHAT WE DID IN KMSDRM_InitMouse(). */
+void
+KMSDRM_DeinitMouse(_THIS)
+{
+ SDL_VideoDevice *video_device = SDL_GetVideoDevice();
+ SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
+ KMSDRM_PlaneInfo info = {0};
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ /* 1- Destroy the curso GBM BO. */
+ if (video_device && dispdata->cursor_bo) {
+ /* Unsethe the cursor BO from the cursor plane.
+ (The other members of the plane info are zeroed). */
+ info.plane = dispdata->cursor_plane;
+ drm_atomic_set_plane_props(&info);
+ /* Wait until the cursor is unset from the cursor plane
+ before destroying it's BO. */
+ if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
+ SDL_SetError("Failed atomic commit in KMSDRM_DenitMouse.");
+ }
+ /* ..and finally destroy the cursor DRM BO! */
+ KMSDRM_gbm_bo_destroy(dispdata->cursor_bo);
+ dispdata->cursor_bo = NULL;
+ }
+
+ /* 2- Free the cursor plane, on which the cursor was being shown. */
+ if (dispdata->cursor_plane) {
+ free_plane(&dispdata->cursor_plane);
+ }
+}
+
void
KMSDRM_InitMouse(_THIS)
{
- /* FIXME: Using UDEV it should be possible to scan all mice
- * but there's no point in doing so as there's no multimice support...yet!
- */
-
SDL_VideoDevice *dev = SDL_GetVideoDevice();
SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
@@ -420,7 +446,7 @@
/***************************************************************************/
/* REMEMBER TO BE SURE OF UNDOING ALL THESE STEPS PROPERLY BEFORE CALLING */
/* gbm_device_destroy, OR YOU WON'T BE ABLE TO CREATE A NEW ONE (ERROR -13 */
- /* ON gbm_create_device). */
+ /* on gbm_create_device). */
/***************************************************************************/
/* 1- Init cursor plane, if we haven't yet. */
@@ -460,8 +486,16 @@
}
}
- /* SDL expects to set the default cursor on screen when we init the mouse. */
- SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
+ /* SDL expects to set the default cursor on screen when we init the mouse,
+ but since we have moved the KMSDRM_InitMouse() call to KMSDRM_CreateWindow(),
+ we end up calling KMSDRM_InitMouse() every time we create a window, so we
+ have to prevent this from being done every time a new window is created.
+ If we don't, new default cursors would stack up on mouse->cursors and SDL
+ would have to hide and delete them at quit, not to mention the memory leak... */
+ if(dispdata->set_default_cursor_pending) {
+ SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
+ dispdata->set_default_cursor_pending = SDL_FALSE;
+ }
return;
@@ -472,40 +506,6 @@
}
}
-void
-KMSDRM_DeinitMouse(_THIS)
-{
- SDL_VideoDevice *video_device = SDL_GetVideoDevice();
- SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
- KMSDRM_PlaneInfo info = {0};
-
- /*******************************************/
- /* UNDO WHAT WE DID IN KMSDRM_InitMouse(). */
- /*******************************************/
-
- /* 1- Destroy the curso GBM BO. */
- if (video_device && dispdata->cursor_bo) {
- /* Unsethe the cursor BO from the cursor plane.
- (The other members of the plane info are zeroed). */
- info.plane = dispdata->cursor_plane;
- drm_atomic_set_plane_props(&info);
- /* Wait until the cursor is unset from the cursor plane
- before destroying it's BO. */
- if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
- SDL_SetError("Failed atomic commit in KMSDRM_DenitMouse.");
- }
- /* ..and finally destroy the cursor DRM BO! */
- KMSDRM_gbm_bo_destroy(dispdata->cursor_bo);
- dispdata->cursor_bo = NULL;
- }
-
- /* 2- Free the cursor plane, on which the cursor was being shown. */
- if (dispdata->cursor_plane) {
- free_plane(&dispdata->cursor_plane);
- }
-
-}
-
/* This is called when a mouse motion event occurs */
static void
KMSDRM_MoveCursor(SDL_Cursor * cursor)
diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index 788a03b..91916de 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -287,7 +287,8 @@
/**********************************************************************************/
/* In double-buffer mode, atomic_commit will always be synchronous/blocking (ie: */
- /* won't return until the requested changes are really done). */ /* Also, there's no need to fence KMS or the GPU, because we won't be entering */
+ /* won't return until the requested changes are really done). */
+ /* Also, there's no need to fence KMS or the GPU, because we won't be entering */
/* game loop again (hence not building or executing a new cmdstring) until */
/* pageflip is done, so we don't need to protect the KMS/GPU access to the buffer.*/
/**********************************************************************************/
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index b68646c..c94f8b2 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -57,6 +57,8 @@
#define KMSDRM_DRI_PATH "/dev/dri/"
+
+
static int set_client_caps (int fd)
{
if (KMSDRM_drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1)) {
@@ -164,161 +166,6 @@
return -ENOENT;
}
-#if 0
-
-/**********************/
-/* 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;
-
- dumb_buffer *ret = SDL_calloc(1, sizeof(*ret));
- if (!ret) {
- SDL_OutOfMemory();
- return NULL;
- }
-
- /*
- * 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) {
- .width = dispdata->mode.hdisplay,
- .height = dispdata->mode.vdisplay,
- .bpp = 32,
- };
-
- if (KMSDRM_drmIoctl(viddata->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create)) {
- SDL_SetError("failed to create dumb buffer\n");
- goto err;
- }
-
- 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],
- };
-
- 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,
- viddata->drm_fd, map.offset);
-
- 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);
- *buffer = NULL;
-}
-
-/* Using the CPU mapping, fill the dumb buffer with black pixels. */
-static void
-KMSDRM_FillDumbBuffer(dumb_buffer *buffer)
-{
- unsigned int x, y;
- for (y = 0; y < buffer->height; y++) {
- uint32_t *pix = (uint32_t *) ((uint8_t *) buffer->dumb.mem + (y * buffer->pitches[0]));
- for (x = 0; x < buffer->width; x++) {
- *pix++ = (0x00000000);
- }
- }
-}
-
-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. */
-/***************************/
-
-#endif
-
/*********************************/
/* Atomic helper functions block */
/*********************************/
@@ -1161,20 +1008,8 @@
/* Figure out the default mode to be set. */
dispdata->mode = crtc->mode;
- /* Find the connector's preferred mode, to be used in case the current mode
- is not valid, or if restoring the current mode fails.
- We can always count on the preferred mode! */
- for (i = 0; i < connector->count_modes; i++) {
- if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
- dispdata->preferred_mode = connector->modes[i];
- }
- }
-
- /* If the current CRTC's mode isn't valid, select the preferred
- mode of the connector. */
- if (crtc->mode_valid == 0) {
- dispdata->mode = dispdata->preferred_mode;
- }
+ /* Save the original mode for restoration on quit. */
+ dispdata->original_mode = dispdata->mode;
if (dispdata->mode.hdisplay == 0 || dispdata->mode.vdisplay == 0 ) {
ret = SDL_SetError("Couldn't get a valid connector videomode.");
@@ -1360,15 +1195,17 @@
#if 1
/************************************************************/
/* Make the display plane point to the original TTY buffer. */
+ /* We have to configure it's input and output scaling */
+ /* parameters accordingly. */
/************************************************************/
plane_info.plane = dispdata->display_plane;
plane_info.crtc_id = dispdata->crtc->crtc->crtc_id;
plane_info.fb_id = dispdata->crtc->crtc->buffer_id;
- 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;
+ plane_info.src_w = dispdata->original_mode.hdisplay;
+ plane_info.src_h = dispdata->original_mode.vdisplay;
+ plane_info.crtc_w = dispdata->original_mode.hdisplay;
+ plane_info.crtc_h = dispdata->original_mode.vdisplay;
drm_atomic_set_plane_props(&plane_info);
@@ -1426,9 +1263,16 @@
int ret = 0;
- if (((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) ||
- ((window->flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)) {
+ /* If the current window already has surfaces, destroy them before creating other.
+ This is mainly for ReconfigureWindow(), where we simply call CreateSurfaces()
+ for regenerating a window's surfaces. */
+ if (windata->gs) {
+ KMSDRM_DestroySurfaces(_this, window);
+ }
+ if ( ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
+ || ((window->flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN))
+ {
width = dispdata->mode.hdisplay;
height = dispdata->mode.vdisplay;
} else {
@@ -1436,11 +1280,14 @@
height = window->h;
}
- if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev, surface_fmt, surface_flags)) {
- SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
+ if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev,
+ surface_fmt, surface_flags)) {
+ SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO,
+ "GBM surface format not supported. Trying anyway.");
}
- windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, width, height, surface_fmt, surface_flags);
+ windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev,
+ width, height, surface_fmt, surface_flags);
if (!windata->gs) {
return SDL_SetError("Could not create GBM surface");
@@ -1562,8 +1409,10 @@
windata->output_x = 0;
} else {
- /* Normal non-fullscreen windows are scaled using the CRTC,
- so get output (CRTC) size and position, for AR correction. */
+ /* Normal non-fullscreen windows are scaled using the PRIMARY PLANE, so here we store:
+ input size (ie: the size of the window buffers),
+ output size (ie: th mode configured on the CRTC), an X position to compensate for AR correction.
+ These are used when we set the PRIMARY PLANE props in SwapWindow() */
ratio = (float)window->w / (float)window->h;
windata->src_w = window->w;
windata->src_h = window->h;
@@ -1637,6 +1486,13 @@
SDL_EVDEV_Init();
#endif
+ /* Since we create and show the default cursor on KMSDRM_InitMouse() and
+ we call KMSDRM_InitMouse() everytime we create a new window, we have
+ to be sure to create and show the default cursor only the first time.
+ If we don't, new default cursors would stack up on mouse->cursors and SDL
+ would have to hide and delete them at quit, not to mention the memory leak... */
+ dispdata->set_default_cursor_pending = SDL_TRUE;
+
viddata->video_init = SDL_TRUE;
cleanup:
@@ -1821,7 +1677,7 @@
so we do it here. */
KMSDRM_InitMouse(_this);
- /* Since we take cursor buffer way from the cursor plane and
+ /* Since we take cursor buffer away from the cursor plane and
destroy the cursor GBM BO when we destroy a window, we must
also manually re-show the cursor on screen, if necessary,
when we create a window. */
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index cc7a1f9..da08a92 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -83,7 +83,7 @@
typedef struct SDL_DisplayData
{
drmModeModeInfo mode;
- drmModeModeInfo preferred_mode;
+ drmModeModeInfo original_mode;
plane *display_plane;
plane *cursor_plane;
@@ -110,6 +110,8 @@
struct gbm_bo *cursor_bo;
uint64_t cursor_w, cursor_h;
+ SDL_bool set_default_cursor_pending;
+
} SDL_DisplayData;
/* Driverdata info that gives KMSDRM-side support and substance to the SDL_Window. */
diff --git a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_mouse.c b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_mouse.c
index 7fa7259..e84c9ad 100644
--- a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_mouse.c
+++ b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_mouse.c
@@ -38,6 +38,21 @@
static void KMSDRM_LEGACY_WarpMouse(SDL_Window * window, int x, int y);
static int KMSDRM_LEGACY_WarpMouseGlobal(int x, int y);
+/**************************************************************************************/
+/* BEFORE CODING ANYTHING MOUSE/CURSOR RELATED, REMEMBER THIS. */
+/* How does SDL manage cursors internally? First, mouse =! cursor. The mouse can have */
+/* many cursors in mouse->cursors. */
+/* -SDL tells us to create a cursor with KMSDRM_CreateCursor(). It can create many */
+/* cursosr with this, not only one. */
+/* -SDL stores those cursors in a cursors array, in mouse->cursors. */
+/* -Whenever it wants (or the programmer wants) takes a cursor from that array */
+/* and shows it on screen with KMSDRM_ShowCursor(). */
+/* KMSDRM_ShowCursor() simply shows or hides the cursor it receives: it does NOT */
+/* mind if it's mouse->cur_cursor, etc. */
+/* -If KMSDRM_ShowCursor() returns succesfully, that cursor becomes mouse->cur_cursor */
+/* and mouse->cursor_shown is 1. */
+/**************************************************************************************/
+
static SDL_Cursor *
KMSDRM_LEGACY_CreateDefaultCursor(void)
{
@@ -68,43 +83,6 @@
(*pixel) = (((uint32_t)A << 24) | ((uint32_t)R << 16) | ((uint32_t)G << 8)) | ((uint32_t)B << 0);
}
-/* Evaluate if a given cursor size is supported or not.
- Notably, current Intel gfx only support 64x64 and up. */
-static SDL_bool
-KMSDRM_LEGACY_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {
-
- SDL_VideoDevice *dev = SDL_GetVideoDevice();
- SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
- SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
-
- int ret;
- uint32_t bo_handle;
- struct gbm_bo *bo = KMSDRM_LEGACY_gbm_bo_create(viddata->gbm_dev, w, h, bo_format,
- GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
-
- if (!bo) {
- SDL_SetError("Could not create GBM cursor BO width size %dx%d for size testing", w, h);
- goto cleanup;
- }
-
- bo_handle = KMSDRM_LEGACY_gbm_bo_get_handle(bo).u32;
- ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id, bo_handle, w, h);
-
- if (ret) {
- goto cleanup;
- }
- else {
- KMSDRM_LEGACY_gbm_bo_destroy(bo);
- return SDL_TRUE;
- }
-
-cleanup:
- if (bo) {
- KMSDRM_LEGACY_gbm_bo_destroy(bo);
- }
- return SDL_FALSE;
-}
-
/* This simply gets the cursor soft-buffer ready.
We don't copy it to a GBO BO until ShowCursor() because the cusor GBM BO (living
in dispata) is destroyed and recreated when we recreate windows, etc. */
@@ -212,7 +190,7 @@
KMSDRM_LEGACY_ShowCursor(mouse->cur_cursor);
}
-/* Show the specified cursor, or hide if cursor is NULL. */
+/* Show the specified cursor, or hide if cursor is NULL or has no focus. */
static int
KMSDRM_LEGACY_ShowCursor(SDL_Cursor * cursor)
{
@@ -255,10 +233,6 @@
/************************************************/
/* If cursor != NULL, DO show cursor on display */
/************************************************/
- if (!dispdata) {
- return SDL_SetError("Could not get display driverdata.");
- }
-
curdata = (KMSDRM_LEGACY_CursorData *) cursor->driverdata;
if (!curdata || !dispdata->cursor_bo) {
@@ -318,8 +292,7 @@
return ret;
}
-/* We have destroyed the cursor by now, in KMSDRM_DestroyCursor.
- This is only for freeing the SDL_cursor.*/
+/* This is only for freeing the SDL_cursor.*/
static void
KMSDRM_LEGACY_FreeCursor(SDL_Cursor * cursor)
{
@@ -450,8 +423,16 @@
}
}
- /* SDL expects to set the default cursor on screen when we init the mouse. */
- SDL_SetDefaultCursor(KMSDRM_LEGACY_CreateDefaultCursor());
+ /* SDL expects to set the default cursor on screen when we init the mouse,
+ but since we have moved the KMSDRM_InitMouse() call to KMSDRM_CreateWindow(),
+ we end up calling KMSDRM_InitMouse() every time we create a window, so we
+ have to prevent this from being done every time a new window is created.
+ If we don't, new default cursors would stack up on mouse->cursors and SDL
+ would have to hide and delete them at quit, not to mention the memory leak... */
+ if(dispdata->set_default_cursor_pending) {
+ SDL_SetDefaultCursor(KMSDRM_LEGACY_CreateDefaultCursor());
+ dispdata->set_default_cursor_pending = SDL_FALSE;
+ }
return;
diff --git a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.c b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.c
index b7607a3..17be847 100644
--- a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.c
+++ b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.c
@@ -62,145 +62,6 @@
#define KMSDRM_LEGACY_DRI_CARDPATHFMT "/dev/dri/card%d"
#endif
-#if 0
-/**************************************************************************************/
-/* UNUSED function because any plane compatible with the CRTC we chose is good enough */
-/* for us, whatever it's type is. Keep it here for documentation purposes. */
-/* It cold be needed sometime in the future, too. */
-/**************************************************************************************/
-
-SDL_bool KMSDRM_IsPlanePrimary (_THIS, drmModePlane *plane) {
-
- SDL_VideoData *viddata = (SDL_VideoData *)_this->driverdata;
- SDL_bool ret = SDL_FALSE;
- int j;
-
- /* Find out if it's a primary plane. */
- drmModeObjectProperties *plane_props =
- KMSDRM_LEGACY_drmModeObjectGetProperties(viddata->drm_fd,
- plane->plane_id, DRM_MODE_OBJECT_ANY);
-
- for (j = 0; (j < plane_props->count_props); j++) {
-
- drmModePropertyRes *prop = KMSDRM_LEGACY_drmModeGetProperty(viddata->drm_fd,
- plane_props->props[j]);
-
- if ((strcmp(prop->name, "type") == 0) &&
- (plane_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY))
- {
- ret = SDL_TRUE;
- }
-
- KMSDRM_LEGACY_drmModeFreeProperty(prop);
-
- }
-
- KMSDRM_LEGACY_drmModeFreeObjectProperties(plane_props);
-
- return ret;
-}
-#endif
-
-#if 0
-/***********************************************/
-/* Use these functions if you ever need info */
-/* about the available planes on your machine. */
-/***********************************************/
-
-void print_plane_info(_THIS, drmModePlanePtr plane)
-{
- char *plane_type;
- drmModeRes *resources;
- uint32_t type = 0;
- SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
- int i;
-
- drmModeObjectPropertiesPtr props = KMSDRM_LEGACY_drmModeObjectGetProperties(viddata->drm_fd,
- plane->plane_id, DRM_MODE_OBJECT_PLANE);
-
- /* Search the plane props for the plane type. */
- for (i = 0; i < props->count_props; i++) {
- drmModePropertyPtr p = KMSDRM_LEGACY_drmModeGetProperty(viddata->drm_fd, props->props[i]);
- if ((strcmp(p->name, "type") == 0)) {
- type = props->prop_values[i];
- }
-
- KMSDRM_LEGACY_drmModeFreeProperty(p);
- }
-
- switch (type) {
- case DRM_PLANE_TYPE_OVERLAY:
- plane_type = "overlay";
- break;
-
- case DRM_PLANE_TYPE_PRIMARY:
- plane_type = "primary";
- break;
-
- case DRM_PLANE_TYPE_CURSOR:
- plane_type = "cursor";
- break;
- }
-
-
- /* Remember that to present a plane on screen, it has to be
- connected to a CRTC so the CRTC scans it,
- scales it, etc... and presents it on screen. */
-
- /* Now we look for the CRTCs supported by the plane. */
- resources = KMSDRM_LEGACY_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 (i = 0; i < resources->count_crtcs; i++) {
- if (plane->possible_crtcs & (1 << i)) {
- uint32_t crtc_id = resources->crtcs[i];
- printf ("%d", crtc_id);
- break;
- }
- }
-
- 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_LEGACY_drmModeGetPlaneResources(viddata->drm_fd);
- if (!plane_resources) {
- printf("drmModeGetPlaneResources failed: %s\n", strerror(errno));
- return;
- }
-
- printf("--Number of planes found: %d-- \n", plane_resources->count_planes);
- printf("--Usable CRTC that we have chosen: %d-- \n", dispdata->crtc->crtc_id);
-
- /* Iterate on all the available planes. */
- for (i = 0; (i < plane_resources->count_planes); i++) {
-
- uint32_t plane_id = plane_resources->planes[i];
-
- drmModePlanePtr plane = KMSDRM_LEGACY_drmModeGetPlane(viddata->drm_fd, plane_id);
- if (!plane) {
- printf("drmModeGetPlane(%u) failed: %s\n", plane_id, strerror(errno));
- continue;
- }
-
- /* Print plane info. */
- print_plane_info(_this, plane);
- KMSDRM_LEGACY_drmModeFreePlane(plane);
- }
-
- KMSDRM_LEGACY_drmModeFreePlaneResources(plane_resources);
-}
-#endif
-
static int
check_modestting(int devindex)
{
@@ -545,13 +406,10 @@
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
drmModeRes *resources = NULL;
- drmModePlaneRes *plane_resources = NULL;
drmModeEncoder *encoder = NULL;
drmModeConnector *connector = NULL;
drmModeCrtc *crtc = NULL;
- uint32_t crtc_index = 0;
-
int ret = 0;
unsigned i,j;
@@ -560,8 +418,6 @@
dispdata->cursor_bo = NULL;
- dispdata->plane_id = 0;
-
/* Open /dev/dri/cardNN (/dev/drmN if on OpenBSD) */
SDL_snprintf(viddata->devpath, sizeof(viddata->devpath), KMSDRM_LEGACY_DRI_CARDPATHFMT, viddata->devindex);
@@ -662,7 +518,6 @@
for (i = 0; i < resources->count_crtcs; i++) {
if (encoder->possible_crtcs & (1 << i)) {
encoder->crtc_id = resources->crtcs[i];
- crtc_index = i;
crtc = KMSDRM_LEGACY_drmModeGetCrtc(viddata->drm_fd, encoder->crtc_id);
break;
}
@@ -680,57 +535,13 @@
/* Save the original mode for restoration on quit. */
dispdata->original_mode = dispdata->mode;
- /* Find the connector's preferred mode, to be used in case the current mode
- is not valid, or if restoring the current mode fails. */
- for (i = 0; i < connector->count_modes; i++) {
- if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
- dispdata->preferred_mode = connector->modes[i];
- }
- }
-
- /* If the current CRTC's mode isn't valid, select the preferred
- mode of the connector. */
- if (crtc->mode_valid == 0) {
- dispdata->mode = dispdata->preferred_mode;
- }
-
if (dispdata->mode.hdisplay == 0 || dispdata->mode.vdisplay == 0 ) {
ret = SDL_SetError("Couldn't get a valid connector videomode.");
goto cleanup;
}
- /*******************************************************/
- /* Look for a plane that can be connected to our CRTC. */
- /*******************************************************/
- plane_resources = KMSDRM_LEGACY_drmModeGetPlaneResources(viddata->drm_fd);
-
- for (i = 0; (i < plane_resources->count_planes); i++) {
-
- drmModePlane *plane = KMSDRM_LEGACY_drmModeGetPlane(viddata->drm_fd,
- plane_resources->planes[i]);
-
- /* 1 - Does this plane support our CRTC?
- 2 - Is this plane unused or used by our CRTC? Both possibilities are good.
- We don't mind if it's primary or overlay. */
- if ((plane->possible_crtcs & (1 << crtc_index)) &&
- (plane->crtc_id == crtc->crtc_id || plane->crtc_id == 0 ))
- {
- dispdata->plane_id = plane->plane_id;
- break;
- }
-
- KMSDRM_LEGACY_drmModeFreePlane(plane);
- }
-
- KMSDRM_LEGACY_drmModeFreePlaneResources(plane_resources);
-
- if (!dispdata->plane_id) {
- ret = SDL_SetError("Could not locate a primary plane compatible with active CRTC.");
- goto cleanup;
- }
-
- /* Store the connector and crtc for future use. These and the plane_id is
- all we keep from this function, and these are just structs, inoffensive to VK. */
+ /* Store the connector and crtc for future use. These are all we keep
+ from this function, and these are just structs, inoffensive to VK. */
dispdata->connector = connector;
dispdata->crtc = crtc;
@@ -900,15 +711,15 @@
int ret = 0;
/* If the current window already has surfaces, destroy them before creating other.
- This is mainly for ReconfigureWindow, where we simply call CreateSurfaces()
+ This is mainly for ReconfigureWindow(), where we simply call CreateSurfaces()
for regenerating a window's surfaces. */
if (windata->gs) {
KMSDRM_LEGACY_DestroySurfaces(_this, window);
}
- if (((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) ||
- ((window->flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)) {
-
+ if ( ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
+ || ((window->flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN))
+ {
width = dispdata->mode.hdisplay;
height = dispdata->mode.vdisplay;
} else {
@@ -1001,6 +812,13 @@
SDL_EVDEV_Init();
#endif
+ /* Since we create and show the default cursor on KMSDRM_InitMouse() and
+ we call KMSDRM_InitMouse() everytime we create a new window, we have
+ to be sure to create and show the default cursor only the first time.
+ If we don't, new default cursors would stack up on mouse->cursors and SDL
+ would have to hide and delete them at quit, not to mention the memory leak... */
+ dispdata->set_default_cursor_pending = SDL_TRUE;
+
viddata->video_init = SDL_TRUE;
cleanup:
@@ -1285,9 +1103,9 @@
/* LEGACY-only hardware, so never use drmModeSetPlane(). */
/***************************************************************************/
- ret = KMSDRM_LEGACY_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc->crtc_id,
- /*fb_info->fb_id*/ -1, 0, 0, &dispdata->connector->connector_id, 1,
- &dispdata->mode);
+ ret = KMSDRM_LEGACY_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc->crtc_id,
+ /*fb_info->fb_id*/ -1, 0, 0, &dispdata->connector->connector_id, 1,
+ &dispdata->mode);
if (ret) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set CRTC");
diff --git a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.h b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.h
index 53a30ea..e1b7d0a 100644
--- a/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.h
+++ b/src/video/kmsdrm_legacy/SDL_kmsdrm_legacy_video.h
@@ -62,12 +62,9 @@
drmModeCrtc *crtc;
drmModeModeInfo mode;
drmModeModeInfo original_mode;
- drmModeModeInfo preferred_mode;
drmModeCrtc *saved_crtc; /* CRTC to restore on quit */
- uint32_t plane_id; /* ID of the primary plane used by the CRTC */
-
SDL_bool gbm_init;
/* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's driverdata struct,
@@ -79,6 +76,8 @@
SDL_bool modeset_pending;
+ SDL_bool set_default_cursor_pending;
+
} SDL_DisplayData;
typedef struct SDL_WindowData