diff --git a/hw/xfree86/drivers/video/modesetting/drmmode_display.c b/hw/xfree86/drivers/video/modesetting/drmmode_display.c index 2210fcf3db..c406c4ffb6 100644 --- a/hw/xfree86/drivers/video/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/video/modesetting/drmmode_display.c @@ -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; diff --git a/hw/xfree86/drivers/video/modesetting/drmmode_display.h b/hw/xfree86/drivers/video/modesetting/drmmode_display.h index 990a19ea2b..d54199ccdb 100644 --- a/hw/xfree86/drivers/video/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/video/modesetting/drmmode_display.h @@ -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 {