summaryrefslogtreecommitdiff
path: root/src/i830_cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i830_cursor.c')
-rw-r--r--src/i830_cursor.c153
1 files changed, 145 insertions, 8 deletions
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 24114192..dfed8cda 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -86,12 +86,14 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
DPRINTF(PFX, "I830InitHWCursor\n");
/* Initialise the HW cursor registers, leaving the cursor hidden. */
- if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
MCURSOR_PIPE_SELECT);
temp |= CURSOR_MODE_DISABLE;
temp |= (pI830->pipe << 28);
+ if(pI830->CursorIsARGB)
+ temp |= MCURSOR_GAMMA_ENABLE;
/* Need to set control, then address. */
OUTREG(CURSOR_A_CONTROL, temp);
if (pI830->CursorIsARGB)
@@ -139,8 +141,8 @@ I830CursorInit(ScreenPtr pScreen)
if (!infoPtr)
return FALSE;
- infoPtr->MaxWidth = 64;
- infoPtr->MaxHeight = 64;
+ infoPtr->MaxWidth = I810_CURSOR_X;
+ infoPtr->MaxHeight = I810_CURSOR_Y;
infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
HARDWARE_CURSOR_INVERT_MASK |
@@ -155,6 +157,8 @@ I830CursorInit(ScreenPtr pScreen)
infoPtr->ShowCursor = I830ShowCursor;
infoPtr->UseHWCursor = I830UseHWCursor;
+ pI830->pCurs = NULL;
+
#ifdef ARGB_CURSOR
pI830->CursorIsARGB = FALSE;
@@ -179,6 +183,8 @@ I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
+ pI830->pCurs = pCurs;
+
DPRINTF(PFX, "I830UseHWCursor\n");
if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical)
return FALSE;
@@ -198,6 +204,52 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
#ifdef ARGB_CURSOR
pI830->CursorIsARGB = FALSE;
#endif
+
+ memset(pcurs, 0, 64 * 64 / 4);
+
+#define GetBit(image, x, y)\
+ ((int)((*(image + ((x) / 8) + ((y) * (128/8))) &\
+ (1 << ( 7 -((x) % 8) ))) ? 1 : 0))
+
+#define SetBit(image, x, y)\
+ (*(image + (x) / 8 + (y) * (128/8)) |=\
+ (int) (1 << (7-((x) % 8))))
+
+ switch (pI830->rotation) {
+ case RR_Rotate_90:
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64; x++) {
+ if (GetBit(src, 64 - y - 1, x))
+ SetBit(pcurs, x, y);
+ if (GetBit(src, 128 - y - 1, x))
+ SetBit(pcurs, x + 64, y);
+ }
+ }
+
+ return;
+ case RR_Rotate_180:
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64; x++) {
+ if (GetBit(src, 64 - x - 1, 64 - y - 1))
+ SetBit(pcurs, x, y);
+ if (GetBit(src, 128 - x - 1, 64 - y - 1))
+ SetBit(pcurs, x + 64, y);
+ }
+ }
+
+ return;
+ case RR_Rotate_270:
+ for (y = 0; y < 64; y++) {
+ for (x = 0; x < 64; x++) {
+ if (GetBit(src, y, 64 - x - 1))
+ SetBit(pcurs, x, y);
+ if (GetBit(src, y + 64, 64 - x - 1))
+ SetBit(pcurs, x + 64, y);
+ }
+ }
+
+ return;
+ }
for (y = 0; y < 64; y++) {
for (x = 0; x < 64 / 4; x++) {
@@ -215,6 +267,9 @@ static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "I830UseHWCursorARGB\n");
+
+ pI830->pCurs = pCurs;
+
if (pScrn->bitsPerPixel == 8)
return FALSE;
@@ -239,13 +294,52 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
if (!image)
return; /* XXX can't happen */
-#ifdef ARGB_CURSOR
pI830->CursorIsARGB = TRUE;
-#endif
w = pCurs->bits->width;
h = pCurs->bits->height;
+ switch (pI830->rotation) {
+ case RR_Rotate_90:
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++)
+ dst[(y) + ((64 - x - 1) * 64)] = *image++;
+ for(; x < 64; x++)
+ dst[(y) + ((64 - x - 1) * 64)] = 0;
+ }
+ for(; y < 64; y++) {
+ for(x = 0; x < 64; x++)
+ dst[(y) + ((64 - x - 1) * 64)] = 0;
+ }
+ return;
+
+ case RR_Rotate_180:
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++)
+ dst[(64 - x - 1) + ((64 - y - 1) * 64)] = *image++;
+ for(; x < 64; x++)
+ dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
+ }
+ for(; y < 64; y++) {
+ for(x = 0; x < 64; x++)
+ dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
+ }
+ return;
+
+ case RR_Rotate_270:
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++)
+ dst[(64 - y - 1) + (x * 64)] = *image++;
+ for(; x < 64; x++)
+ dst[(64 - y - 1) + (x * 64)] = 0;
+ }
+ for(; y < 64; y++) {
+ for(x = 0; x < 64; x++)
+ dst[(64 - y - 1) + (x * 64)] = 0;
+ }
+ return;
+ }
+
for(y = 0; y < h; y++) {
for(x = 0; x < w; x++)
*dst++ = *image++;
@@ -267,7 +361,49 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
CARD32 temp = 0;
static Bool outsideViewport = FALSE;
Bool hide = FALSE, show = FALSE;
+ int oldx = x, oldy = y;
+ int hotspotx = 0, hotspoty = 0;
+
+ oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
+ oldy += pScrn->frameY0;
+
+ switch (pI830->rotation) {
+ case RR_Rotate_0:
+ x = oldx;
+ y = oldy;
+ break;
+ case RR_Rotate_90:
+ x = oldy;
+ y = pScrn->pScreen->width - oldx;
+ hotspoty = I810_CURSOR_X;
+ break;
+ case RR_Rotate_180:
+ x = pScrn->pScreen->width - oldx;
+ y = pScrn->pScreen->height - oldy;
+ hotspotx = I810_CURSOR_X;
+ hotspoty = I810_CURSOR_Y;
+ break;
+ case RR_Rotate_270:
+ x = pScrn->pScreen->height - oldy;
+ y = oldx;
+ hotspotx = I810_CURSOR_Y;
+ break;
+ }
+
+ x -= hotspotx;
+ y -= hotspoty;
+ /* Now, readjust */
+ x -= pScrn->frameX0;
+ y -= pScrn->frameY0;
+
+ /* Clamp the cursor position to the visible screen area */
+ if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1;
+ if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1;
+ if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
+ if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
+
+#if 0
/*
* There is a screen display problem when the cursor position is set
* wholely outside of the viewport. We trap that here, turning the
@@ -283,6 +419,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
show = TRUE;
outsideViewport = FALSE;
}
+#endif
if (x < 0) {
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
@@ -308,7 +445,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
}
/* have to upload the base for the new position */
- if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+ if (IS_I9XX(pI830)) {
if (pI830->CursorIsARGB)
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
else
@@ -339,7 +476,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
pI830->cursorOn = TRUE;
- if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
if (pI830->CursorIsARGB)
@@ -387,7 +524,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
DPRINTF(PFX, "I830HideCursor\n");
pI830->cursorOn = FALSE;
- if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~CURSOR_MODE;
temp |= CURSOR_MODE_DISABLE;