Copyright (c) 2002-2004, Thomas Kurschel
Part of Radeon accelerant
Hardware cursor support.
*/
#include "radeon_accelerant.h"
#include "GlobalData.h"
#include "generic.h"
#include "mmio.h"
#include "crtc_regs.h"
static void moveOneCursor( accelerator_info *ai, int crtc_idx, int x, int y );
void Radeon_SetCursorColors( accelerator_info *ai, int crtc_idx )
{
SHOW_FLOW0( 3, "" );
if( crtc_idx == 0 ) {
OUTREG( ai->regs, RADEON_CUR_CLR0, 0xffffff );
OUTREG( ai->regs, RADEON_CUR_CLR1, 0 );
} else {
OUTREG( ai->regs, RADEON_CUR2_CLR0, 0xffffff );
OUTREG( ai->regs, RADEON_CUR2_CLR1, 0 );
}
}
status_t SET_CURSOR_SHAPE( uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
uint8 *andMask, uint8 *xorMask)
{
virtual_card *vc = ai->vc;
uint8 *fb_cursor = vc->cursor.data;
int row, col_byte;
return B_ERROR;*/
if( hot_x >= width || hot_y >= height )
return B_ERROR;
vc->cursor.hot_x = hot_x;
vc->cursor.hot_y = hot_y;
for( row = 0; row < 64; ++row ) {
for( col_byte = 0; col_byte < 64 / 8; ++col_byte ) {
if( row < height && col_byte < (width + 7) / 8 ) {
fb_cursor[row * 64/8 * 2 + col_byte] = *andMask++;
fb_cursor[row * 64/8 * 2 + col_byte + 64/8] = *xorMask++;
} else {
fb_cursor[row * 64/8 * 2 + col_byte] = 0xff;
fb_cursor[row * 64/8 * 2 + col_byte + 64/8] = 0;
}
}
}
return B_OK;
}
void MOVE_CURSOR(uint16 x, uint16 y)
{
virtual_card *vc = ai->vc;
bool move_screen = false;
uint16 hds, vds;
uint16 h_adjust = 7;
ACQUIRE_BEN( ai->si->engine.lock );
hds = vc->mode.h_display_start;
vds = vc->mode.v_display_start;
if (x >= vc->mode.virtual_width)
x = vc->mode.virtual_width - 1;
if (y >= vc->mode.virtual_height)
y = vc->mode.virtual_height - 1;
if( vc->scroll ) {
if( x >= (vc->mode.timing.h_display + hds) ) {
hds = ((x - vc->mode.timing.h_display) + 1 + h_adjust) & ~h_adjust;
move_screen = true;
} else if( x < hds ) {
hds = x & ~h_adjust;
move_screen = true;
}
if( y >= (vc->mode.timing.v_display + vds) ) {
vds = y - vc->mode.timing.v_display + 1;
move_screen = true;
} else if( y < vds ) {
vds = y;
move_screen = true;
}
if( move_screen )
Radeon_MoveDisplay( ai, hds, vds );
}
x -= hds;
y -= vds;
if( vc->used_crtc[0] )
moveOneCursor( ai, 0, x, y );
if( vc->used_crtc[1] )
moveOneCursor( ai, 1, x, y );
RELEASE_BEN( ai->si->engine.lock );
}
void SHOW_CURSOR( bool is_visible )
{
virtual_card *vc = ai->vc;
SHOW_FLOW0( 4, "" );
ACQUIRE_BEN( ai->si->engine.lock );
vc->cursor.is_visible = is_visible;
if( vc->used_crtc[0] )
Radeon_ShowCursor( ai, 0 );
if( vc->used_crtc[1] )
Radeon_ShowCursor( ai, 1 );
RELEASE_BEN( ai->si->engine.lock );
}
void moveOneCursor( accelerator_info *ai, int crtc_idx, int x, int y )
{
virtual_card *vc = ai->vc;
crtc_info *crtc = &ai->si->crtc[crtc_idx];
int xorigin, yorigin;
bool prev_state;
x -= crtc->rel_x;
y -= crtc->rel_y;
x -= vc->cursor.hot_x;
y -= vc->cursor.hot_y;
prev_state = crtc->cursor_on_screen;
crtc->cursor_on_screen = true;
if( y > crtc->mode.timing.v_display ||
x > crtc->mode.timing.h_display ||
x <= -16 || y <= -16 )
{
crtc->cursor_on_screen = false;
}
if( prev_state != crtc->cursor_on_screen )
Radeon_ShowCursor( ai, crtc_idx );
if( !crtc->cursor_on_screen )
return;
xorigin = 0;
yorigin = 0;
if( x < 0 )
xorigin = -x;
if( y < 0 )
yorigin = -y;
if( crtc_idx == 0 ) {
OUTREG( ai->regs, RADEON_CUR_HORZ_VERT_OFF, RADEON_CUR_LOCK
| (xorigin << 16)
| yorigin );
OUTREG( ai->regs, RADEON_CUR_HORZ_VERT_POSN, RADEON_CUR_LOCK
| ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y) );
OUTREG( ai->regs, RADEON_CUR_OFFSET,
vc->cursor.fb_offset + xorigin + yorigin * 16 );
} else {
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_OFF, RADEON_CUR2_LOCK
| (xorigin << 16)
| yorigin );
OUTREG( ai->regs, RADEON_CUR2_HORZ_VERT_POSN, RADEON_CUR2_LOCK
| ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y) );
OUTREG( ai->regs, RADEON_CUR2_OFFSET,
vc->cursor.fb_offset + xorigin + yorigin * 16 );
}
}
void Radeon_ShowCursor( accelerator_info *ai, int crtc_idx )
{
virtual_card *vc = ai->vc;
crtc_info *crtc = &ai->si->crtc[crtc_idx];
uint32 tmp;
if( crtc_idx == 0 ) {
tmp = INREG( ai->regs, RADEON_CRTC_GEN_CNTL );
if( vc->cursor.is_visible && crtc->cursor_on_screen ) {
tmp |= RADEON_CRTC_CUR_EN;
} else {
tmp &= ~RADEON_CRTC_CUR_EN;
}
OUTREG( ai->regs, RADEON_CRTC_GEN_CNTL, tmp );
} else {
tmp = INREG( ai->regs, RADEON_CRTC2_GEN_CNTL );
if( vc->cursor.is_visible && crtc->cursor_on_screen )
tmp |= RADEON_CRTC2_CUR_EN;
else
tmp &= ~RADEON_CRTC2_CUR_EN;
OUTREG( ai->regs, RADEON_CRTC2_GEN_CNTL, tmp );
}
}