2 Copyright (c) 2002-2004, Thomas Kurschel
5 Part of Radeon accelerant
7 Hardware cursor support.
11 #include "radeon_accelerant.h"
12 #include "GlobalData.h"
15 #include "crtc_regs.h"
17 static void moveOneCursor( accelerator_info
*ai
, int crtc_idx
, int x
, int y
);
19 // set standard foreground/background colours
20 void Radeon_SetCursorColors( accelerator_info
*ai
, int crtc_idx
)
25 OUTREG( ai
->regs
, RADEON_CUR_CLR0
, 0xffffff );
26 OUTREG( ai
->regs
, RADEON_CUR_CLR1
, 0 );
28 OUTREG( ai
->regs
, RADEON_CUR2_CLR0
, 0xffffff );
29 OUTREG( ai
->regs
, RADEON_CUR2_CLR1
, 0 );
33 // public function to set shape of cursor
34 status_t
SET_CURSOR_SHAPE( uint16 width
, uint16 height
, uint16 hot_x
, uint16 hot_y
,
35 uint8
*andMask
, uint8
*xorMask
)
37 virtual_card
*vc
= ai
->vc
;
38 uint8
*fb_cursor
= vc
->cursor
.data
;
41 /* NOTE: Currently, for BeOS, cursor width and height must be equal to 16. */
42 /* if( width != 16 || height != 16 )
45 if( hot_x
>= width
|| hot_y
>= height
)
48 // TBD: should we sync here? I'd say so, but if I fail, we deadlock
50 vc
->cursor
.hot_x
= hot_x
;
51 vc
->cursor
.hot_y
= hot_y
;
53 for( row
= 0; row
< 64; ++row
) {
54 for( col_byte
= 0; col_byte
< 64 / 8; ++col_byte
) {
55 if( row
< height
&& col_byte
< (width
+ 7) / 8 ) {
56 fb_cursor
[row
* 64/8 * 2 + col_byte
] = *andMask
++;
57 fb_cursor
[row
* 64/8 * 2 + col_byte
+ 64/8] = *xorMask
++;
59 fb_cursor
[row
* 64/8 * 2 + col_byte
] = 0xff;
60 fb_cursor
[row
* 64/8 * 2 + col_byte
+ 64/8] = 0;
69 // public function to move cursor
70 void MOVE_CURSOR(uint16 x
, uint16 y
)
72 virtual_card
*vc
= ai
->vc
;
73 bool move_screen
= false;
76 // alignment mask for horizontal position
79 ACQUIRE_BEN( ai
->si
->engine
.lock
);
81 hds
= vc
->mode
.h_display_start
;
82 vds
= vc
->mode
.v_display_start
;
84 // clamp cursor (negative positions are impossible due to uint16)
85 if (x
>= vc
->mode
.virtual_width
)
86 x
= vc
->mode
.virtual_width
- 1;
87 if (y
>= vc
->mode
.virtual_height
)
88 y
= vc
->mode
.virtual_height
- 1;
90 // if scrolling enabled, i.e. we have a larger virtual screen,
91 // pan display accordingly
93 if( x
>= (vc
->mode
.timing
.h_display
+ hds
) ) {
94 hds
= ((x
- vc
->mode
.timing
.h_display
) + 1 + h_adjust
) & ~h_adjust
;
96 } else if( x
< hds
) {
100 if( y
>= (vc
->mode
.timing
.v_display
+ vds
) ) {
101 vds
= y
- vc
->mode
.timing
.v_display
+ 1;
103 } else if( y
< vds
) {
109 Radeon_MoveDisplay( ai
, hds
, vds
);
112 // adjust according to virtual screen position
117 if( vc
->used_crtc
[0] )
118 moveOneCursor( ai
, 0, x
, y
);
119 if( vc
->used_crtc
[1] )
120 moveOneCursor( ai
, 1, x
, y
);
122 RELEASE_BEN( ai
->si
->engine
.lock
);
126 // public function to show cursor
127 void SHOW_CURSOR( bool is_visible
)
129 virtual_card
*vc
= ai
->vc
;
133 ACQUIRE_BEN( ai
->si
->engine
.lock
);
135 // this is the public statement
136 vc
->cursor
.is_visible
= is_visible
;
138 // the following functions take also care to not
139 // show the cursor if it's on the other port
140 if( vc
->used_crtc
[0] )
141 Radeon_ShowCursor( ai
, 0 );
142 if( vc
->used_crtc
[1] )
143 Radeon_ShowCursor( ai
, 1 );
145 RELEASE_BEN( ai
->si
->engine
.lock
);
149 // move cursor on one port
150 // main_port - common data is stored here
151 void moveOneCursor( accelerator_info
*ai
, int crtc_idx
, int x
, int y
)
153 virtual_card
*vc
= ai
->vc
;
154 crtc_info
*crtc
= &ai
->si
->crtc
[crtc_idx
];
155 int xorigin
, yorigin
;
158 // adjust according to relative screen position
163 x
-= vc
->cursor
.hot_x
;
164 y
-= vc
->cursor
.hot_y
;
166 // check whether the cursor is (partially) visible on this screen
167 prev_state
= crtc
->cursor_on_screen
;
168 crtc
->cursor_on_screen
= true;
170 // in theory, cursor can be up to 64 pixels off screen,
171 // but there were display errors
172 if( y
> crtc
->mode
.timing
.v_display
||
173 x
> crtc
->mode
.timing
.h_display
||
174 x
<= -16 || y
<= -16 )
176 crtc
->cursor_on_screen
= false;
179 if( prev_state
!= crtc
->cursor_on_screen
)
180 Radeon_ShowCursor( ai
, crtc_idx
);
182 if( !crtc
->cursor_on_screen
)
185 // if upper-left corner of cursor is outside of
186 // screen, we have to use special registers to clip it
196 if( crtc_idx
== 0 ) {
197 OUTREG( ai
->regs
, RADEON_CUR_HORZ_VERT_OFF
, RADEON_CUR_LOCK
200 OUTREG( ai
->regs
, RADEON_CUR_HORZ_VERT_POSN
, RADEON_CUR_LOCK
201 | ((xorigin
? 0 : x
) << 16)
202 | (yorigin
? 0 : y
) );
203 OUTREG( ai
->regs
, RADEON_CUR_OFFSET
,
204 vc
->cursor
.fb_offset
+ xorigin
+ yorigin
* 16 );
206 OUTREG( ai
->regs
, RADEON_CUR2_HORZ_VERT_OFF
, RADEON_CUR2_LOCK
209 OUTREG( ai
->regs
, RADEON_CUR2_HORZ_VERT_POSN
, RADEON_CUR2_LOCK
210 | ((xorigin
? 0 : x
) << 16)
211 | (yorigin
? 0 : y
) );
212 OUTREG( ai
->regs
, RADEON_CUR2_OFFSET
,
213 vc
->cursor
.fb_offset
+ xorigin
+ yorigin
* 16 );
218 // show cursor on one port, depending on official whishes and whether
219 // cursor is located on this subscreen
220 void Radeon_ShowCursor( accelerator_info
*ai
, int crtc_idx
)
222 virtual_card
*vc
= ai
->vc
;
223 crtc_info
*crtc
= &ai
->si
->crtc
[crtc_idx
];
226 if( crtc_idx
== 0 ) {
227 tmp
= INREG( ai
->regs
, RADEON_CRTC_GEN_CNTL
);
229 if( vc
->cursor
.is_visible
&& crtc
->cursor_on_screen
) {
230 tmp
|= RADEON_CRTC_CUR_EN
;
232 tmp
&= ~RADEON_CRTC_CUR_EN
;
235 OUTREG( ai
->regs
, RADEON_CRTC_GEN_CNTL
, tmp
);
238 tmp
= INREG( ai
->regs
, RADEON_CRTC2_GEN_CNTL
);
240 if( vc
->cursor
.is_visible
&& crtc
->cursor_on_screen
)
241 tmp
|= RADEON_CRTC2_CUR_EN
;
243 tmp
&= ~RADEON_CRTC2_CUR_EN
;
245 OUTREG( ai
->regs
, RADEON_CRTC2_GEN_CNTL
, tmp
);