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
6465static 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
18811882static 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
19091917static 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
19311927drmmode_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
19821968static 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 */
46564657Bool
46574658drmmode_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.
0 commit comments