modesetting: handle pitch when painting the hardware cursor

The cursor pitch can depend on crtc.

Since we only use the sizes reported by SIZE_HINTS,
we can allocate a small cache for pitches in each crtc.

Signed-off-by: stefan11111 <stefan11111@shitposting.expert>
This commit is contained in:
stefan11111
2025-08-20 16:59:40 +03:00
committed by Enrico Weigelt
parent 56c4d68140
commit b11c28b13e
2 changed files with 68 additions and 14 deletions

View File

@@ -1830,6 +1830,66 @@ drmmode_set_cursor(xf86CrtcPtr crtc, int width, int height)
return TRUE;
}
static int
drmmode_cursor_get_pitch(drmmode_crtc_private_ptr drmmode_crtc, int idx)
{
drmmode_ptr drmmode = drmmode_crtc->drmmode;
drmmode_cursor_ptr drmmode_cursor = &drmmode_crtc->cursor;
int width = drmmode_cursor->dimensions[idx].width;
int height = drmmode_cursor->dimensions[idx].height;
int num_pitches = drmmode_cursor->num_dimensions;
if (!drmmode_crtc->cursor_pitches) {
drmmode_crtc->cursor_pitches = calloc(num_pitches, sizeof(int));
if (!drmmode_crtc->cursor_pitches) {
/* we couldn't allocate memory for the cache, so we don't cache the result */
int ret;
struct dumb_bo *bo = dumb_bo_create(drmmode->fd, width, height, drmmode->kbpp);
if (!bo) {
/* We couldn't allocate a bo, so we try to guess the pitch */
return width > 64 ? width : 64;
}
ret = bo->pitch / drmmode->cpp;
dumb_bo_destroy(drmmode->fd, bo);
return ret;
}
}
if (drmmode_crtc->cursor_pitches[idx]) {
/* return the cached pitch */
return drmmode_crtc->cursor_pitches[idx];
}
struct dumb_bo *bo = dumb_bo_create(drmmode->fd, width, height, drmmode->kbpp);
if (!bo) {
/* We couldn't allocate a bo, so we try to guess the pitch */
return width > 64 ? width : 64;
}
drmmode_crtc->cursor_pitches[idx] = bo->pitch / drmmode->cpp;
dumb_bo_destroy(drmmode->fd, bo);
return drmmode_crtc->cursor_pitches[idx];
}
static void
drmmode_paint_cursor(CARD32 * restrict cursor, int cursor_pitch, int cursor_width, int cursor_height,
const CARD32 * restrict image, int image_width, int image_height)
{
if (cursor_width == image_width && cursor_pitch == cursor_width) {
/* we can speed things up in this case */
memcpy(cursor, image, cursor_width * cursor_height * sizeof(*cursor));
} else {
for (int i = 0; i < cursor_height; i++) {
memcpy(cursor + i * cursor_pitch, image + i * image_width, cursor_width * sizeof(*cursor)); /* cpu_to_le32(image[i]); */
}
}
}
static void drmmode_hide_cursor(xf86CrtcPtr crtc);
static inline int
@@ -1857,12 +1917,8 @@ drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
drmmode_cursor_rec drmmode_cursor = drmmode_crtc->cursor;
int width, height, x, y, i;
int width, height, i;
int max_width, max_height;
uint32_t *ptr;
/* cursor should be mapped already */
ptr = (uint32_t *) (drmmode_cursor.bo->ptr);
/* We need to know what our limit is for HW cursors. */
max_width = get_maximum_cursor_width(drmmode_cursor);
@@ -1882,16 +1938,11 @@ drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
width = drmmode_cursor.dimensions[i].width;
height = drmmode_cursor.dimensions[i].height;
/* Copy the cursor image over. */
i = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
ptr[i++] = image[y * max_width + x];
}
const int cursor_pitch = drmmode_cursor_get_pitch(drmmode_crtc, i);
/* Clear the remainder for good measure. */
for (; i < max_width * max_height; i++)
ptr[i++] = 0;
/* cursor should be mapped already */
drmmode_paint_cursor(drmmode_cursor.bo->ptr, cursor_pitch, width, height,
image, max_width, max_height);
/* set cursor width and height here for drmmode_show_cursor */
drmmode_crtc->cursor_width = width;
@@ -2274,6 +2325,7 @@ drmmode_crtc_destroy(xf86CrtcPtr crtc)
/* Used even without atomic modesetting */
free(drmmode_crtc->cursor.dimensions);
free(drmmode_crtc->cursor_pitches);
if (!ms->atomic_modeset)
return;

View File

@@ -245,6 +245,8 @@ typedef struct {
Bool vrr_enabled;
Bool use_gamma_lut;
int* cursor_pitches;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {