xfree86: Fix rotation of 2-color non-interleaved cursor images
When RandR 1.2's transformation code is enabled, it rotates the cursor image so that it appears upright on a rotated screen. This code completely mangles 2-color cursors on hardware where the the mask and source images are not interleaved due to two problems: 1. stride is calculated as (width / 4) rather than (width / 8), so the expression (y * stride) skips two lines instead of one for every time y is incremented. 2. cursor_bitpos ignores the 'mask' parameter if the hardware doesn't specify any of the HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_* flags. To fix this, refactor the code to pass the whole xf86CursorInfoPtr through to cursor_bitpos and compute the correct stride there based on the flags. If none of the SOURCE_MASK_INTERLEAVE flags are set, use the total cursor size to move the 'image' variable into the mask part of the image before computing the desired byte pointer. Signed-off-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Robert Morell <rmorell@nvidia.com> Reviewed-by: Alex Deucher <alexdeucher@gmail.com> Tested-by: Cyril Brulebois <kibi@debian.org>
This commit is contained in:
		
							parent
							
								
									23e3d1f233
								
							
						
					
					
						commit
						ffcbfa0063
					
				|  | @ -1,5 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright © 2007 Keith Packard |  * Copyright © 2007 Keith Packard | ||||||
|  |  * Copyright © 2010 Aaron Plattner | ||||||
|  * |  * | ||||||
|  * Permission to use, copy, modify, distribute, and sell this software and its |  * Permission to use, copy, modify, distribute, and sell this software and its | ||||||
|  * documentation for any purpose is hereby granted without fee, provided that |  * documentation for any purpose is hereby granted without fee, provided that | ||||||
|  | @ -126,12 +127,33 @@ xf86_crtc_rotate_coord_back (Rotation    rotation, | ||||||
|     *y_src = y_dst; |     *y_src = y_dst; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct cursor_bit { | ||||||
|  |     CARD8 *byte; | ||||||
|  |     char bitpos; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Convert an x coordinate to a position within the cursor bitmap |  * Convert an x coordinate to a position within the cursor bitmap | ||||||
|  */ |  */ | ||||||
| static int | static struct cursor_bit | ||||||
| cursor_bitpos (int flags, int x, Bool mask) | cursor_bitpos (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, | ||||||
|  | 	       Bool mask) | ||||||
| { | { | ||||||
|  |     const int flags = cursor_info->Flags; | ||||||
|  |     const Bool interleaved = | ||||||
|  | 	!!(flags & (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | | ||||||
|  | 		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 | | ||||||
|  | 		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 | | ||||||
|  | 		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | | ||||||
|  | 		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)); | ||||||
|  |     const int width = cursor_info->MaxWidth; | ||||||
|  |     const int height = cursor_info->MaxHeight; | ||||||
|  |     const int stride = interleaved ? width / 4 : width / 8; | ||||||
|  | 
 | ||||||
|  |     struct cursor_bit ret; | ||||||
|  | 
 | ||||||
|  |     image += y * stride; | ||||||
|  | 
 | ||||||
|     if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) |     if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) | ||||||
| 	mask = !mask; | 	mask = !mask; | ||||||
|     if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) |     if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) | ||||||
|  | @ -149,29 +171,33 @@ cursor_bitpos (int flags, int x, Bool mask) | ||||||
| 	x = ((x & ~31) << 1) | (mask << 5) | (x & 31); | 	x = ((x & ~31) << 1) | (mask << 5) | (x & 31); | ||||||
|     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64) |     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64) | ||||||
| 	x = ((x & ~63) << 1) | (mask << 6) | (x & 63); | 	x = ((x & ~63) << 1) | (mask << 6) | (x & 63); | ||||||
|     return x; |     else if (mask) | ||||||
|  | 	image += stride * height; | ||||||
|  | 
 | ||||||
|  |     ret.byte = image + (x / 8); | ||||||
|  |     ret.bitpos = x & 7; | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Fetch one bit from a cursor bitmap |  * Fetch one bit from a cursor bitmap | ||||||
|  */ |  */ | ||||||
| static CARD8 | static CARD8 | ||||||
| get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask) | get_bit (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask) | ||||||
| { | { | ||||||
|     x = cursor_bitpos (flags, x, mask); |     struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask); | ||||||
|     image += y * stride; |     return (*bit.byte >> bit.bitpos) & 1; | ||||||
|     return (image[(x >> 3)] >> (x & 7)) & 1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Set one bit in a cursor bitmap |  * Set one bit in a cursor bitmap | ||||||
|  */ |  */ | ||||||
| static void | static void | ||||||
| set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask) | set_bit (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask) | ||||||
| { | { | ||||||
|     x = cursor_bitpos (flags, x, mask); |     struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask); | ||||||
|     image += y * stride; |     *bit.byte |= 1 << bit.bitpos; | ||||||
|     image[(x >> 3)] |= 1 << (x & 7); |  | ||||||
| } | } | ||||||
|      |      | ||||||
| /*
 | /*
 | ||||||
|  | @ -186,7 +212,6 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src) | ||||||
|     CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image; |     CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image; | ||||||
|     int			x, y; |     int			x, y; | ||||||
|     int			xin, yin; |     int			xin, yin; | ||||||
|     int			stride = cursor_info->MaxWidth >> 2; |  | ||||||
|     int			flags = cursor_info->Flags; |     int			flags = cursor_info->Flags; | ||||||
|     CARD32		bits; |     CARD32		bits; | ||||||
| 
 | 
 | ||||||
|  | @ -201,10 +226,10 @@ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src) | ||||||
| 				    cursor_info->MaxWidth, | 				    cursor_info->MaxWidth, | ||||||
| 				    cursor_info->MaxHeight, | 				    cursor_info->MaxHeight, | ||||||
| 				    x, y, &xin, &yin); | 				    x, y, &xin, &yin); | ||||||
| 	    if (get_bit (src, stride, flags, xin, yin, TRUE) == | 	    if (get_bit (src, cursor_info, xin, yin, TRUE) == | ||||||
| 		((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) | 		((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) | ||||||
| 	    { | 	    { | ||||||
| 		if (get_bit (src, stride, flags, xin, yin, FALSE)) | 		if (get_bit (src, cursor_info, xin, yin, FALSE)) | ||||||
| 		    bits = xf86_config->cursor_fg; | 		    bits = xf86_config->cursor_fg; | ||||||
| 		else | 		else | ||||||
| 		    bits = xf86_config->cursor_bg; | 		    bits = xf86_config->cursor_bg; | ||||||
|  | @ -407,7 +432,6 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src) | ||||||
|         int x, y; |         int x, y; | ||||||
|     	int xin, yin; |     	int xin, yin; | ||||||
| 	int stride = cursor_info->MaxWidth >> 2; | 	int stride = cursor_info->MaxWidth >> 2; | ||||||
| 	int flags = cursor_info->Flags; |  | ||||||
| 	 | 	 | ||||||
| 	cursor_image = xf86_config->cursor_image; | 	cursor_image = xf86_config->cursor_image; | ||||||
| 	memset(cursor_image, 0, cursor_info->MaxHeight * stride); | 	memset(cursor_image, 0, cursor_info->MaxHeight * stride); | ||||||
|  | @ -419,10 +443,10 @@ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src) | ||||||
| 					cursor_info->MaxWidth, | 					cursor_info->MaxWidth, | ||||||
| 					cursor_info->MaxHeight, | 					cursor_info->MaxHeight, | ||||||
| 					x, y, &xin, &yin); | 					x, y, &xin, &yin); | ||||||
| 		if (get_bit(src, stride, flags, xin, yin, FALSE)) | 		if (get_bit(src, cursor_info, xin, yin, FALSE)) | ||||||
| 		    set_bit(cursor_image, stride, flags, x, y, FALSE); | 		    set_bit(cursor_image, cursor_info, x, y, FALSE); | ||||||
| 		if (get_bit(src, stride, flags, xin, yin, TRUE)) | 		if (get_bit(src, cursor_info, xin, yin, TRUE)) | ||||||
| 		    set_bit(cursor_image, stride, flags, x, y, TRUE); | 		    set_bit(cursor_image, cursor_info, x, y, TRUE); | ||||||
| 	    } | 	    } | ||||||
|     } |     } | ||||||
|     crtc->funcs->load_cursor_image (crtc, cursor_image); |     crtc->funcs->load_cursor_image (crtc, cursor_image); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue