Skip to content

Commit d35d531

Browse files
committed
modesetting: Initialize the cursor image with the smallest size supported by all CRTCs.
We try to find the smallest size we can use for the cursor image. It has to be at least 64x64, otherwise we get a broken cursor image. Signed-off-by: stefan11111 <[email protected]>
1 parent cc408b2 commit d35d531

File tree

4 files changed

+76
-98
lines changed

4 files changed

+76
-98
lines changed

hw/xfree86/drivers/video/modesetting/driver.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,14 +1959,9 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
19591959
PointPriv->spriteFuncs = &drmmode_sprite_funcs;
19601960
}
19611961

1962-
/* Get the maximum cursor size. */
1963-
drmmode_cursor_dim_rec cursor_dim = { 0 };
1964-
if (!drmmode_get_largest_cursor(pScrn, &cursor_dim))
1965-
return FALSE;
1966-
19671962
/* Need to extend HWcursor support to handle mask interleave */
19681963
if (!ms->drmmode.sw_cursor)
1969-
xf86_cursors_init(pScreen, cursor_dim.width, cursor_dim.height,
1964+
xf86_cursors_init(pScreen, ms->cursor_image_width, ms->cursor_image_height,
19701965
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
19711966
HARDWARE_CURSOR_UPDATE_UNHIDDEN |
19721967
HARDWARE_CURSOR_ARGB);

hw/xfree86/drivers/video/modesetting/driver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ typedef struct _modesettingRec {
131131
DamagePtr damage;
132132
Bool dirty_enabled;
133133

134+
uint32_t cursor_image_width;
135+
uint32_t cursor_image_height;
136+
134137
Bool has_queue_sequence;
135138
Bool tried_queue_sequence;
136139

hw/xfree86/drivers/video/modesetting/drmmode_display.c

Lines changed: 70 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959

6060
#include "driver.h"
6161

62+
#define MIN(a,b) ((a) < (b) ? (a) : (b))
6263
#define MAX(a,b) ((a) > (b) ? (a) : (b))
6364

6465
static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
@@ -1825,10 +1826,10 @@ drmmode_set_cursor(xf86CrtcPtr crtc, int width, int height)
18251826
drmmode_crtc->drmmode->sw_cursor = TRUE;
18261827
}
18271828

1828-
if (ret)
1829+
if (ret) {
18291830
/* fallback to swcursor */
18301831
return FALSE;
1831-
1832+
}
18321833
return TRUE;
18331834
}
18341835

@@ -1879,24 +1880,31 @@ drmmode_cursor_get_pitch(drmmode_crtc_private_ptr drmmode_crtc, int idx)
18791880
}
18801881

18811882
static void
1882-
drmmode_paint_cursor(CARD32 * restrict cursor, int cursor_pitch, int cursor_width, int cursor_height,
1883+
drmmode_paint_cursor(struct dumb_bo *cursor_bo, int cursor_pitch, int cursor_width, int cursor_height,
18831884
const CARD32 * restrict image, int image_width, int image_height,
18841885
drmmode_crtc_private_ptr restrict drmmode_crtc, int glyph_width, int glyph_height)
18851886
{
18861887
int width_todo;
18871888
int height_todo;
18881889

1890+
CARD32 *cursor = cursor_bo->ptr;
1891+
1892+
/*
1893+
* The image buffer can be smaller than the cursor buffer.
1894+
* This means that we can't clear the cursor by copying '\0' bytes
1895+
* from the image buffer, because we might read out of bounds.
1896+
*/
18891897
if (drmmode_crtc->cursor_glyph_width == 0 &&
18901898
drmmode_crtc->cursor_glyph_height == 0) {
18911899
/* If this is the first time we paint the cursor, assume the entire cursor buffer is dirty */
1892-
width_todo = cursor_width;
1893-
height_todo = cursor_height;
1894-
} else {
1895-
/* Paint only what we need to */
1896-
width_todo = MAX(drmmode_crtc->cursor_glyph_width, glyph_width);
1897-
height_todo = MAX(drmmode_crtc->cursor_glyph_height, glyph_height);
1900+
/* XXX Do we really need to do this? XXX */
1901+
memset(cursor, 0, cursor_bo->size);
18981902
}
18991903

1904+
/* Paint only what we need to */
1905+
width_todo = MAX(drmmode_crtc->cursor_glyph_width, glyph_width);
1906+
height_todo = MAX(drmmode_crtc->cursor_glyph_height, glyph_height);
1907+
19001908
/* remember the size of the current cursor glyph */
19011909
drmmode_crtc->cursor_glyph_width = glyph_width;
19021910
drmmode_crtc->cursor_glyph_height = glyph_height;
@@ -1908,18 +1916,6 @@ drmmode_paint_cursor(CARD32 * restrict cursor, int cursor_pitch, int cursor_widt
19081916

19091917
static void drmmode_hide_cursor(xf86CrtcPtr crtc);
19101918

1911-
static inline int
1912-
get_maximum_cursor_width(drmmode_cursor_rec cursor)
1913-
{
1914-
return cursor.dimensions[cursor.num_dimensions - 1].width;
1915-
}
1916-
1917-
static inline int
1918-
get_maximum_cursor_height(drmmode_cursor_rec cursor)
1919-
{
1920-
return cursor.dimensions[cursor.num_dimensions - 1].height;
1921-
}
1922-
19231919
/*
19241920
* The load_cursor_argb_check driver hook.
19251921
*
@@ -1931,14 +1927,10 @@ static Bool
19311927
drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
19321928
{
19331929
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1930+
modesettingPtr ms = modesettingPTR(crtc->scrn);
19341931
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
19351932
drmmode_cursor_rec drmmode_cursor = drmmode_crtc->cursor;
1936-
int width, height, i;
1937-
int max_width, max_height;
1938-
1939-
/* We need to know what our limit is for HW cursors. */
1940-
max_width = get_maximum_cursor_width(drmmode_cursor);
1941-
max_height = get_maximum_cursor_height(drmmode_cursor);
1933+
int i;
19421934

19431935
/* Find the most compatiable size. */
19441936
for (i = 0; i < drmmode_cursor.num_dimensions; i++)
@@ -1949,34 +1941,28 @@ drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
19491941
dimensions.height >= cursor->bits->height) {
19501942
break;
19511943
}
1952-
1953-
if (dimensions.width > max_width ||
1954-
dimensions.height > max_height) {
1955-
1956-
/* If this ever happens, i should not be 0, but check for good measure */
1957-
if (i > 0) {
1958-
i--;
1959-
}
1960-
break;
1961-
}
19621944
}
19631945

1946+
const int cursor_pitch = drmmode_cursor_get_pitch(drmmode_crtc, i);
1947+
19641948
/* Get the resolution of the cursor. */
1965-
width = drmmode_cursor.dimensions[i].width;
1966-
height = drmmode_cursor.dimensions[i].height;
1949+
int cursor_width = drmmode_cursor.dimensions[i].width;
1950+
int cursor_height = drmmode_cursor.dimensions[i].height;
19671951

1968-
const int cursor_pitch = drmmode_cursor_get_pitch(drmmode_crtc, i);
1952+
/* Get the size of the cursor image buffer */
1953+
int image_width = ms->cursor_image_width;
1954+
int image_height = ms->cursor_image_height;
19691955

19701956
/* cursor should be mapped already */
1971-
drmmode_paint_cursor(drmmode_cursor.bo->ptr, cursor_pitch, width, height,
1972-
image, max_width, max_height,
1957+
drmmode_paint_cursor(drmmode_cursor.bo, cursor_pitch, cursor_width, cursor_height,
1958+
image, image_width, image_height,
19731959
drmmode_crtc, cursor->bits->width, cursor->bits->height);
19741960

19751961
/* set cursor width and height here for drmmode_show_cursor */
1976-
drmmode_crtc->cursor_width = width;
1977-
drmmode_crtc->cursor_height = height;
1962+
drmmode_crtc->cursor_width = cursor_width;
1963+
drmmode_crtc->cursor_height = cursor_height;
19781964

1979-
return drmmode_crtc->cursor_up ? drmmode_set_cursor(crtc, width, height) : TRUE;
1965+
return drmmode_crtc->cursor_up ? drmmode_set_cursor(crtc, cursor_width, cursor_height) : TRUE;
19801966
}
19811967

19821968
static void
@@ -4652,43 +4638,71 @@ drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
46524638
#endif
46534639
}
46544640

4641+
static Bool
4642+
drmmode_get_smallest_supported_cursor(drmmode_cursor_rec cursor, int *owidth, int *oheight)
4643+
{
4644+
for (int i = 0; i < cursor.num_dimensions; i++) {
4645+
if (cursor.dimensions[i].width >= 64 &&
4646+
cursor.dimensions[i].height >= 64) {
4647+
*owidth = cursor.dimensions[i].width;
4648+
*oheight = cursor.dimensions[i].height;
4649+
return TRUE;
4650+
}
4651+
}
4652+
4653+
return FALSE;
4654+
}
4655+
46554656
/* create front and cursor BOs */
46564657
Bool
46574658
drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
46584659
{
46594660
modesettingPtr ms = modesettingPTR(pScrn);
46604661
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
4661-
int width;
4662-
int height;
46634662
int bpp = ms->drmmode.kbpp;
4664-
int i;
46654663
int cpp = (bpp + 7) / 8;
46664664

4665+
int width, height;
4666+
uint32_t min_width = 1 << 30, min_height = 1 << 30;
4667+
46674668
width = pScrn->virtualX;
46684669
height = pScrn->virtualY;
46694670

46704671
if (!drmmode_create_bo(drmmode, &drmmode->front_bo, width, height, bpp))
46714672
return FALSE;
46724673
pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
46734674

4674-
bpp = 32;
4675-
4676-
for (i = 0; i < xf86_config->num_crtc; i++) {
4675+
for (int i = 0; i < xf86_config->num_crtc; i++) {
46774676
xf86CrtcPtr crtc = xf86_config->crtc[i];
46784677
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
46794678
drmmode_cursor_rec cursor = drmmode_crtc->cursor;
4680-
4681-
/* If we don't have any dimensions then
4679+
4680+
/* If we don't have any dimensions then
46824681
* something has gone terribly wrong. */
46834682
assert(cursor.num_dimensions);
46844683

4685-
/* Use the maximum available size. */
4686-
width = get_maximum_cursor_width(cursor);
4687-
height = get_maximum_cursor_height(cursor);
4684+
/* Use the minimum available size. */
4685+
/* We need the size to be at least 64x64 */
4686+
if(!drmmode_get_smallest_supported_cursor(cursor, &width, &height)) {
4687+
xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
4688+
"Could not create cursor buffer that is at least 64x64\n");
4689+
drmmode_free_bos(pScrn, drmmode);
4690+
return FALSE;
4691+
}
4692+
4693+
/* We take the minimum of the sizes here
4694+
* so that we don't get a cursor glyph larger
4695+
* that a crtc's cursor buffer
4696+
* Both are >= 64, guaranteed by above */
4697+
min_width = MIN(width, min_width);
4698+
min_height = MIN(height, min_height);
46884699

46894700
drmmode_crtc->cursor.bo = dumb_bo_create(drmmode->fd, width, height, bpp);
46904701
}
46914702

4703+
ms->cursor_image_width = min_width;
4704+
ms->cursor_image_height = min_height;
4705+
46924706
return TRUE;
46934707
}
46944708

@@ -4823,38 +4837,6 @@ drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled)
48234837
drmmode_crtc->vrr_enabled = enabled;
48244838
}
48254839

4826-
Bool drmmode_get_largest_cursor(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim)
4827-
{
4828-
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
4829-
4830-
/* We need the cursor image to be at least 64x64 */
4831-
int max_width = 64, max_height = 64;
4832-
4833-
if (!cursor_lim)
4834-
return FALSE;
4835-
4836-
for (int i = 0; i < xf86_config->num_crtc; i++) {
4837-
xf86CrtcPtr crtc = xf86_config->crtc[i];
4838-
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
4839-
drmmode_cursor_rec cursor = drmmode_crtc->cursor;
4840-
4841-
/* Get the largest cursor available. */
4842-
drmmode_cursor_dim_rec largest = cursor.dimensions[cursor.num_dimensions - 1];
4843-
4844-
int width = largest.width;
4845-
int height = largest.height;
4846-
4847-
/* Future work:
4848-
* - We should only let sizes that all CRTCs support. */
4849-
max_width = MAX(width, max_width);
4850-
max_height = MAX(height, max_height);
4851-
}
4852-
4853-
cursor_lim->width = max_width;
4854-
cursor_lim->height = max_height;
4855-
return TRUE;
4856-
}
4857-
48584840
/*
48594841
* We hook the screen's cursor-sprite (swcursor) functions to see if a swcursor
48604842
* is active. When a swcursor is active we disable page-flipping.

hw/xfree86/drivers/video/modesetting/drmmode_display.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ typedef struct {
235235

236236
uint64_t next_msc;
237237

238-
int cursor_width, cursor_height;
238+
int cursor_width;
239+
int cursor_height;
239240

240241
Bool need_modeset;
241242
struct xorg_list mode_list;
@@ -359,7 +360,4 @@ Bool drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y);
359360

360361
void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
361362
void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
362-
363-
Bool drmmode_get_largest_cursor(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim);
364-
365363
#endif

0 commit comments

Comments
 (0)