mirror of
https://github.com/X11Libre/xserver.git
synced 2026-04-14 17:18:09 +00:00
modesetting: probe using the old method if SIZE_HINTS isn't available
On most cards, SIZE_HINTS isn't available. Without this, most users would have to set the fallback cursor size themselves, or rely on the 64x64 default. Signed-off-by: stefan11111 <stefan11111@shitposting.expert>
This commit is contained in:
committed by
Enrico Weigelt
parent
6f7731c44c
commit
cf092cd469
@@ -1931,6 +1931,7 @@ drmmode_paint_cursor(struct dumb_bo *cursor_bo, int cursor_pitch, int cursor_wid
|
||||
}
|
||||
|
||||
static void drmmode_hide_cursor(xf86CrtcPtr crtc);
|
||||
static void drmmode_probe_cursor_size(xf86CrtcPtr crtc);
|
||||
|
||||
/*
|
||||
* The load_cursor_argb_check driver hook.
|
||||
@@ -1945,9 +1946,17 @@ drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
modesettingPtr ms = modesettingPTR(crtc->scrn);
|
||||
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
|
||||
drmmode_cursor_rec drmmode_cursor = drmmode_crtc->cursor;
|
||||
int i;
|
||||
|
||||
if (drmmode_crtc->cursor_up) {
|
||||
/* we probe the cursor so late, because we want to make sure that
|
||||
the screen is fully initialized and something is already drawn on it.
|
||||
Otherwise, we can't get reliable results with the probe. */
|
||||
drmmode_probe_cursor_size(crtc);
|
||||
}
|
||||
|
||||
drmmode_cursor_rec drmmode_cursor = drmmode_crtc->cursor;
|
||||
|
||||
/* Find the most compatiable size. */
|
||||
for (i = 0; i < drmmode_cursor.num_dimensions; i++)
|
||||
{
|
||||
@@ -2507,6 +2516,8 @@ populate_cursor_sizes(drmmode_ptr drmmode, drmmode_crtc_private_ptr drmmode_crtc
|
||||
drmmode_crtc->cursor.dimensions[idx].width = size_hint.width;
|
||||
drmmode_crtc->cursor.dimensions[idx].height = size_hint.height;
|
||||
}
|
||||
|
||||
drmmode_crtc->cursor_probed = TRUE;
|
||||
fail:
|
||||
drmModeFreePropertyBlob(blob);
|
||||
}
|
||||
@@ -2806,8 +2817,34 @@ drmmode_crtc_vrr_init(int drm_fd, xf86CrtcPtr crtc)
|
||||
drmModeFreeObjectProperties(drm_props);
|
||||
}
|
||||
|
||||
static drmmode_cursor_dim_rec
|
||||
drmmode_cursor_get_fallback(drmmode_crtc_private_ptr drmmode_crtc)
|
||||
{
|
||||
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||
drmmode_cursor_dim_rec fallback;
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
/* We begin by using the largest supported cursor, and change it later,
|
||||
when we can reliably probe for the smallest suppored cursor size */
|
||||
int ret1 = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_WIDTH, &value);
|
||||
fallback.width = value;
|
||||
|
||||
int ret2 = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_HEIGHT, &value);
|
||||
fallback.height = value;
|
||||
|
||||
/* 64x64 is the safest fallback value to use when we can't probe in any other way,
|
||||
* as it is the default value that KMS uses. */
|
||||
if (ret1 || ret2) {
|
||||
fallback.width = 64;
|
||||
fallback.height = 64;
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, drmmode_cursor_dim_rec fallback, int num)
|
||||
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
|
||||
{
|
||||
xf86CrtcPtr crtc;
|
||||
drmmode_crtc_private_ptr drmmode_crtc;
|
||||
@@ -2838,8 +2875,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
|
||||
drmmode_crtc->cursor.num_dimensions = 1;
|
||||
drmmode_crtc->cursor.dimensions = xnfalloc(sizeof(drmmode_cursor_dim_rec));
|
||||
|
||||
drmmode_crtc->cursor.dimensions[0].width = fallback.width;
|
||||
drmmode_crtc->cursor.dimensions[0].height = fallback.height;
|
||||
drmmode_crtc->cursor.dimensions[0] = drmmode_cursor_get_fallback(drmmode_crtc);
|
||||
|
||||
props = drmModeObjectGetProperties(drmmode->fd, mode_res->crtcs[num],
|
||||
DRM_MODE_OBJECT_CRTC);
|
||||
@@ -4164,27 +4200,12 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
|
||||
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
|
||||
"Up to %d crtcs needed for screen.\n", crtcs_needed);
|
||||
|
||||
drmmode_cursor_dim_rec fallback;
|
||||
|
||||
int ret1 = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_WIDTH, &value);
|
||||
fallback.width = value;
|
||||
|
||||
int ret2 = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_HEIGHT, &value);
|
||||
fallback.height = value;
|
||||
|
||||
/* This is the safest fallback value as
|
||||
* it is the default value that KMS uses. */
|
||||
if (ret1 || ret2) {
|
||||
fallback.width = 64;
|
||||
fallback.height = 64;
|
||||
}
|
||||
|
||||
xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width,
|
||||
mode_res->max_height);
|
||||
for (i = 0; i < mode_res->count_crtcs; i++)
|
||||
if (!xf86IsEntityShared(pScrn->entityList[0]) ||
|
||||
(crtcs_needed && !(ms_ent->assigned_crtcs & (1 << i))))
|
||||
crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, fallback, i);
|
||||
crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
|
||||
|
||||
/* All ZaphodHeads outputs provided with matching crtcs? */
|
||||
if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
|
||||
@@ -4652,6 +4673,149 @@ drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
drmmode_reset_cursor(drmmode_crtc_private_ptr drmmode_crtc)
|
||||
{
|
||||
/* Mark the entire cursor buffer as dirty */
|
||||
drmmode_crtc->cursor_glyph_width = 0;
|
||||
drmmode_crtc->cursor_glyph_height = 0;
|
||||
drmmode_crtc->old_pitch = 0;
|
||||
|
||||
/* If we had any cursor pitches for the old cursor, they are no longer valid now */
|
||||
free(drmmode_crtc->cursor_pitches);
|
||||
drmmode_crtc->cursor_pitches = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the old probe method for the minimum cursor size.
|
||||
* This is only used if the SIZE_HINTS probe fails.
|
||||
*/
|
||||
static void drmmode_probe_cursor_size(xf86CrtcPtr crtc)
|
||||
{
|
||||
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
|
||||
uint32_t handle = drmmode_crtc->cursor.bo->handle;
|
||||
drmmode_ptr drmmode = drmmode_crtc->drmmode;
|
||||
drmmode_cursor_ptr drmmode_cursor = &drmmode_crtc->cursor;
|
||||
int width, height, size;
|
||||
int max_width, max_height;
|
||||
int min_width, min_height;
|
||||
|
||||
if (drmmode_crtc->cursor_probed) {
|
||||
return;
|
||||
}
|
||||
|
||||
drmmode_crtc->cursor_probed = TRUE;
|
||||
|
||||
xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING,
|
||||
"Probing the cursor size using the old method\n");
|
||||
|
||||
/* If we're here, we only have one size, the fallback size */
|
||||
max_width = drmmode_cursor->dimensions[0].width;
|
||||
max_height = drmmode_cursor->dimensions[0].height;
|
||||
|
||||
min_width = max_width;
|
||||
min_height = max_height;
|
||||
|
||||
/* probe square min first */
|
||||
for (size = 1; size <= max_width &&
|
||||
size <= max_height; size *= 2) {
|
||||
int ret;
|
||||
|
||||
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
handle, size, size, 0, 0);
|
||||
if (ret == 0) {
|
||||
min_width = size;
|
||||
min_height = size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if smaller width works with non-square */
|
||||
for (width = 1; width <= size; width *= 2) {
|
||||
int ret;
|
||||
|
||||
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
handle, width, size, 0, 0);
|
||||
if (ret == 0) {
|
||||
min_width = width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if smaller height works with non-square */
|
||||
for (height = 1; height <= size; height *= 2) {
|
||||
int ret;
|
||||
|
||||
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
|
||||
handle, size, height, 0, 0);
|
||||
if (ret == 0) {
|
||||
min_height = height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, 0, 0);
|
||||
|
||||
if (min_width == max_width && min_height == max_height) {
|
||||
xf86DrvMsgVerb(crtc->scrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
|
||||
"Cursor size: %dx%d\n",
|
||||
min_width, min_height);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
drmmode_reset_cursor(drmmode_crtc);
|
||||
|
||||
/*
|
||||
* We could add as many sizes as we want here.
|
||||
* We want the minimum size to be here, and we need the maximum size to be here,
|
||||
* because that's what we initialize the cursor image with, and we could theoretically
|
||||
* get cursor glyph sizes that big.
|
||||
*
|
||||
* There is no problem with multiple sizes being equal here.
|
||||
* We want dimensions[i] <= dimensions[i + 1] for all i, but even if
|
||||
* this doesn't happen, there shouldn't be any issues.
|
||||
*/
|
||||
|
||||
int num_dimensions = 1;
|
||||
if (min_width > min_height) {
|
||||
for(int j = min_height; j <= min_width; j *= 2) {
|
||||
num_dimensions++;
|
||||
}
|
||||
} else {
|
||||
for(int j = min_width; j <= min_height; j *= 2) {
|
||||
num_dimensions++;
|
||||
}
|
||||
|
||||
}
|
||||
drmmode_cursor->num_dimensions = num_dimensions;
|
||||
drmmode_cursor->dimensions = xnfrealloc(drmmode_cursor->dimensions, num_dimensions * sizeof(drmmode_cursor_dim_rec));
|
||||
|
||||
if (min_width > min_height) {
|
||||
int idx = 0;
|
||||
for(int j = min_height; j <= min_width; j *= 2) {
|
||||
drmmode_cursor->dimensions[idx].width = min_width;
|
||||
drmmode_cursor->dimensions[idx].height = j;
|
||||
idx++;
|
||||
}
|
||||
} else {
|
||||
int idx = 0;
|
||||
for(int j = min_width; j <= min_height; j *= 2) {
|
||||
drmmode_cursor->dimensions[idx].width = j;
|
||||
drmmode_cursor->dimensions[idx].height = min_height;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* maximum size */
|
||||
drmmode_cursor->dimensions[num_dimensions - 1].width = max_width;
|
||||
drmmode_cursor->dimensions[num_dimensions - 1].height = max_height;
|
||||
|
||||
xf86DrvMsgVerb(crtc->scrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
|
||||
"Minimum cursor size: %dx%d\n",
|
||||
min_width, min_height);
|
||||
}
|
||||
|
||||
/* create front and cursor BOs */
|
||||
Bool
|
||||
drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
|
||||
|
||||
@@ -252,6 +252,8 @@ typedef struct {
|
||||
uint32_t cursor_glyph_height;
|
||||
int old_pitch;
|
||||
|
||||
Bool cursor_probed;
|
||||
|
||||
int* cursor_pitches;
|
||||
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user