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.c200
1 files changed, 176 insertions, 24 deletions
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 9f2baa3a..d59c19dd 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -46,6 +46,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Keith Whitwell <keith@tungstengraphics.com>
* David Dawes <dawes@xfree86.org>
*
+ * Updated for Dual Head capabilities:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
+ * Add ARGB HW cursor support:
+ * Alan Hourihane <alanh@tungstengraphics.com>
+ *
*/
#include "xf86.h"
@@ -63,6 +69,10 @@ static void I830HideCursor(ScrnInfoPtr pScrn);
static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb);
static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
static Bool I830UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs);
+#ifdef ARGB_CURSOR
+static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
+static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
+#endif
void
I830InitHWCursor(ScrnInfoPtr pScrn)
@@ -71,24 +81,28 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
CARD32 temp;
DPRINTF(PFX, "I830InitHWCursor\n");
-
/* Initialise the HW cursor registers, leaving the cursor hidden. */
- if (IS_MOBILE(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
MCURSOR_PIPE_SELECT);
temp |= CURSOR_MODE_DISABLE;
- /*
- * XXX Should enable cursor B when both pipes are enabled.
- * For now, give pipe A preference.
- */
- if (pI830->pipeEnabled[0])
- temp |= MCURSOR_PIPE_A;
- else if (pI830->pipeEnabled[1])
- temp |= MCURSOR_PIPE_B;
+ temp |= (pI830->pipe << 28);
/* Need to set control, then address. */
OUTREG(CURSOR_A_CONTROL, temp);
- OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ temp &= ~MCURSOR_PIPE_SELECT;
+ temp |= (!pI830->pipe << 28);
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
@@ -97,7 +111,10 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
/* This initialises the format and leave the cursor disabled. */
OUTREG(CURSOR_CONTROL, temp);
/* Need to set address and size after disabling. */
- OUTREG(CURSOR_BASEADDR, pI830->CursorMem.Start);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
+ else
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
OUTREG(CURSOR_SIZE, temp);
@@ -134,7 +151,17 @@ I830CursorInit(ScreenPtr pScreen)
infoPtr->ShowCursor = I830ShowCursor;
infoPtr->UseHWCursor = I830UseHWCursor;
- if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical)
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = FALSE;
+
+ if (pI830->CursorMemARGB->Start) {
+ /* Use ARGB if we were able to allocate the 16kb needed */
+ infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
+ infoPtr->LoadCursorARGB = I830LoadCursorARGB;
+ }
+#endif
+
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical)
return FALSE;
I830HideCursor(pScrn);
@@ -149,7 +176,7 @@ I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "I830UseHWCursor\n");
- if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical)
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical)
return FALSE;
return TRUE;
@@ -159,10 +186,15 @@ static void
I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
{
I830Ptr pI830 = I830PTR(pScrn);
- CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem.Start);
+ CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem->Start);
int x, y;
DPRINTF(PFX, "I830LoadCursorImage\n");
+
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = FALSE;
+#endif
+
for (y = 0; y < 64; y++) {
for (x = 0; x < 64 / 4; x++) {
*pcurs++ = *src++;
@@ -170,6 +202,59 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
}
}
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ DPRINTF(PFX, "I830UseHWCursorARGB\n");
+ if (pScrn->bitsPerPixel == 8)
+ return FALSE;
+
+ if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical)
+ return FALSE;
+
+ if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start);
+ CARD32 *image = (CARD32 *)pCurs->bits->argb;
+ int x, y, w, h;
+
+ DPRINTF(PFX, "I830LoadCursorARGB\n");
+
+ if (!image)
+ return; /* XXX can't happen */
+
+#ifdef ARGB_CURSOR
+ pI830->CursorIsARGB = TRUE;
+#endif
+
+ w = pCurs->bits->width;
+ h = pCurs->bits->height;
+
+ for(y = 0; y < h; y++) {
+ for(x = 0; x < w; x++)
+ *dst++ = *image++;
+ for(; x < 64; x++)
+ *dst++ = 0;
+ }
+
+ for(; y < 64; y++) {
+ for(x = 0; x < 64; x++)
+ *dst++ = 0;
+ }
+}
+#endif
static void
I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
@@ -207,6 +292,8 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
OUTREG(CURSOR_A_POSITION, temp);
+ if (pI830->Clone)
+ OUTREG(CURSOR_B_POSITION, temp);
if (pI830->cursorOn) {
if (hide)
@@ -215,6 +302,20 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
pI830->CursorInfoRec->ShowCursor(pScrn);
pI830->cursorOn = TRUE;
}
+
+ /* have to upload the base for the new position */
+ if (IS_I915G(pI830)) {
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
+ }
}
static void
@@ -225,22 +326,51 @@ I830ShowCursor(ScrnInfoPtr pScrn)
DPRINTF(PFX, "I830ShowCursor\n");
DPRINTF(PFX,
- "Value of CursorMem.Physical is %x, "
- " Value of CursorMem.Start is %x ",
- pI830->CursorMem.Physical, pI830->CursorMem.Start);
+ "Value of CursorMem->Physical is %x, "
+ " Value of CursorMem->Start is %x ",
+ pI830->CursorMem->Physical, pI830->CursorMem->Start);
+ DPRINTF(PFX,
+ "Value of CursorMemARGB->Physical is %x, "
+ " Value of CursorMemARGB->Start is %x ",
+ pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
pI830->cursorOn = TRUE;
- if (IS_MOBILE(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
- temp &= ~CURSOR_MODE;
- temp |= CURSOR_MODE_64_4C_AX;
+ temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+ if (pI830->CursorIsARGB)
+ temp |= CURSOR_MODE_64_ARGB_AX;
+ else
+ temp |= CURSOR_MODE_64_4C_AX;
+ temp |= (pI830->pipe << 28); /* Connect to correct pipe */
/* Need to set mode, then address. */
OUTREG(CURSOR_A_CONTROL, temp);
- OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ temp &= ~MCURSOR_PIPE_SELECT;
+ temp |= (!pI830->pipe << 28);
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
} else {
temp = INREG(CURSOR_CONTROL);
+ temp &= ~(CURSOR_FORMAT_MASK);
temp |= CURSOR_ENABLE;
+ if (pI830->CursorIsARGB)
+ temp |= CURSOR_FORMAT_ARGB;
+ else
+ temp |= CURSOR_FORMAT_3C;
OUTREG(CURSOR_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
+ else
+ OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
}
}
@@ -253,13 +383,23 @@ I830HideCursor(ScrnInfoPtr pScrn)
DPRINTF(PFX, "I830HideCursor\n");
pI830->cursorOn = FALSE;
- if (IS_MOBILE(pI830)) {
+ if (IS_MOBILE(pI830) || IS_I915G(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~CURSOR_MODE;
temp |= CURSOR_MODE_DISABLE;
OUTREG(CURSOR_A_CONTROL, temp);
/* This is needed to flush the above change. */
- OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
+ if (pI830->Clone) {
+ OUTREG(CURSOR_B_CONTROL, temp);
+ if (pI830->CursorIsARGB)
+ OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
+ else
+ OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
+ }
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~CURSOR_ENABLE;
@@ -272,10 +412,22 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
I830Ptr pI830 = I830PTR(pScrn);
+#ifdef ARGB_CURSOR
+ /* Don't recolour cursors set with SetCursorARGB. */
+ if (pI830->CursorIsARGB)
+ return;
+#endif
+
DPRINTF(PFX, "I830SetCursorColors\n");
OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
+ if (pI830->Clone) {
+ OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
+ OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff);
+ }
}