xenocara/driver/xf86-video-ast/src/ast_cursor.c
2006-11-26 19:59:49 +00:00

393 lines
14 KiB
C

/*
* Copyright (c) 2005 ASPEED Technology Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the authors not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. The authors makes no representations
* about the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86RAC.h"
#include "xf86cmap.h"
#include "compiler.h"
#include "mibstore.h"
#include "vgaHW.h"
#include "mipointer.h"
#include "micmap.h"
#include "fb.h"
#include "regionstr.h"
#include "xf86xv.h"
#include <X11/extensions/Xv.h>
#include "vbe.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
/* framebuffer offscreen manager */
#include "xf86fbman.h"
/* include xaa includes */
#include "xaa.h"
#include "xaarop.h"
/* H/W cursor support */
#include "xf86Cursor.h"
#include "cursorstr.h"
/* Driver specific headers */
#include "ast.h"
#ifdef HWC
/* Prototype type declaration */
Bool ASTCursorInit(ScreenPtr pScreen);
Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST);
static void ASTShowCursor(ScrnInfoPtr pScrn);
static void ASTHideCursor(ScrnInfoPtr pScrn);
static void ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
static void ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
static void ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src);
static Bool ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
static void ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
static Bool ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
static void ASTFireCursor(ScrnInfoPtr pScrn);
Bool
ASTCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
ASTRecPtr pAST = ASTPTR(pScrn);
xf86CursorInfoPtr infoPtr;
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr) return FALSE;
pAST->HWCInfoPtr = infoPtr;
infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_INVERT_MASK |
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
infoPtr->MaxWidth = MAX_HWC_WIDTH;
infoPtr->MaxHeight = MAX_HWC_HEIGHT;
infoPtr->ShowCursor = ASTShowCursor;
infoPtr->HideCursor = ASTHideCursor;
infoPtr->SetCursorPosition = ASTSetCursorPosition;
infoPtr->SetCursorColors = ASTSetCursorColors;
infoPtr->LoadCursorImage = ASTLoadCursorImage;
infoPtr->UseHWCursor = ASTUseHWCursor;
#ifdef ARGB_CURSOR
infoPtr->UseHWCursorARGB = ASTUseHWCursorARGB;
infoPtr->LoadCursorARGB = ASTLoadCursorARGB;
#endif
return(xf86InitCursor(pScreen, infoPtr));
}
Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST)
{
ScreenPtr pScreen;
/* init cursor cache info */
/* Set HWC_NUM in Options instead */
/* pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; */
pAST->HWCInfo.HWC_NUM_Next = 0;
/* allocate HWC cache */
if (!pAST->pHWCPtr) {
pScreen = screenInfo.screens[pScrn->scrnIndex];
pAST->pHWCPtr = xf86AllocateOffscreenLinear (pScreen, (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM, HWC_ALIGN, NULL, NULL, NULL);
if (!pAST->pHWCPtr) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Allocate HWC Cache failed \n");
return (FALSE);
}
pAST->HWCInfo.ulHWCOffsetAddr = pAST->pHWCPtr->offset*((pScrn->bitsPerPixel + 1) / 8);
pAST->HWCInfo.pjHWCVirtualAddr = pAST->FBVirtualAddr + pAST->HWCInfo.ulHWCOffsetAddr;
}
return (TRUE);
}
static void
ASTShowCursor(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR jReg;
jReg= 0x02;
if (pAST->HWCInfo.cursortype ==HWC_COLOR)
jReg |= 0x01;
SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, jReg); /* enable mono */
}
static void
ASTHideCursor(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, 0x00); /* disable HWC */
}
static void
ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
ASTRecPtr pAST = ASTPTR(pScrn);
DisplayModePtr mode = pAST->ModePtr;
int x_offset, y_offset;
UCHAR *pjSignature;
/* Set cursor info to Offscreen */
pjSignature = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
*((ULONG *) (pjSignature + HWC_SIGNATURE_X)) = x;
*((ULONG *) (pjSignature + HWC_SIGNATURE_Y)) = y;
x_offset = pAST->HWCInfo.offset_x;
y_offset = pAST->HWCInfo.offset_y;
if(x < 0) {
x_offset = (-x) + pAST->HWCInfo.offset_x;
x = 0;
}
if(y < 0) {
y_offset = (-y) + pAST->HWCInfo.offset_y;
y = 0;
}
if(mode->Flags & V_DBLSCAN) y *= 2;
/* Set to Reg. */
SetIndexReg(CRTC_PORT, 0xC2, (UCHAR) (x_offset));
SetIndexReg(CRTC_PORT, 0xC3, (UCHAR) (y_offset));
SetIndexReg(CRTC_PORT, 0xC4, (UCHAR) (x & 0xFF));
SetIndexReg(CRTC_PORT, 0xC5, (UCHAR) ((x >> 8) & 0x0F));
SetIndexReg(CRTC_PORT, 0xC6, (UCHAR) (y & 0xFF));
SetIndexReg(CRTC_PORT, 0xC7, (UCHAR) ((y >> 8) & 0x07));
/* Fire HWC */
ASTFireCursor(pScrn);
}
static void
ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
ASTRecPtr pAST = ASTPTR(pScrn);
pAST->HWCInfo.fg = (fg & 0x0F) | (((fg>>8) & 0x0F) << 4) | (((fg>>16) & 0x0F) << 8);
pAST->HWCInfo.bg = (bg & 0x0F) | (((bg>>8) & 0x0F) << 4) | (((bg>>16) & 0x0F) << 8);
}
static void
ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src)
{
ASTRecPtr pAST = ASTPTR(pScrn);
int i, j, k;
UCHAR *pjSrcAnd, *pjSrcXor, *pjDstData;
ULONG ulTempDstAnd32[2], ulTempDstXor32[2], ulTempDstData32[2];
UCHAR jTempSrcAnd32, jTempSrcXor32;
ULONG ulCheckSum = 0;
ULONG ulPatternAddr;
/* init cursor info. */
pAST->HWCInfo.cursortype = HWC_MONO;
pAST->HWCInfo.width = (USHORT) MAX_HWC_WIDTH;
pAST->HWCInfo.height = (USHORT) MAX_HWC_HEIGHT;
pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
/* copy cursor image to cache */
pjSrcXor = src;
pjSrcAnd = src + (MAX_HWC_WIDTH*MAX_HWC_HEIGHT/8);
pjDstData = pAST->HWCInfo.pjHWCVirtualAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next;
for (j = 0; j < MAX_HWC_HEIGHT; j++)
{
for (i = 0; i < (MAX_HWC_WIDTH/8); i++ )
{
for (k=7; k>0; k-=2)
{
jTempSrcAnd32 = *((UCHAR *) pjSrcAnd);
jTempSrcXor32 = *((UCHAR *) pjSrcXor);
ulTempDstAnd32[0] = ((jTempSrcAnd32 >> k) & 0x01) ? 0x00008000L:0x00L;
ulTempDstXor32[0] = ((jTempSrcXor32 >> k) & 0x01) ? 0x00004000L:0x00L;
ulTempDstData32[0] = ((jTempSrcXor32 >> k) & 0x01) ? pAST->HWCInfo.fg:pAST->HWCInfo.bg;
ulTempDstAnd32[1] = ((jTempSrcAnd32 >> (k-1)) & 0x01) ? 0x80000000L:0x00L;
ulTempDstXor32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? 0x40000000L:0x00L;
ulTempDstData32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? (pAST->HWCInfo.fg << 16):(pAST->HWCInfo.bg << 16);
*((ULONG *) pjDstData) = ulTempDstAnd32[0] | ulTempDstXor32[0] | ulTempDstData32[0] | ulTempDstAnd32[1] | ulTempDstXor32[1] | ulTempDstData32[1];
ulCheckSum += *((ULONG *) pjDstData);
pjDstData += 4;
}
pjSrcAnd ++;
pjSrcXor ++;
}
}
/* Write Checksum as signature */
pjDstData = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
*((ULONG *) pjDstData) = ulCheckSum;
*((ULONG *) (pjDstData + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
*((ULONG *) (pjDstData + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
*((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTX)) = 0;
*((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTY)) = 0;
/* set pattern offset */
ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
/* update HWC_NUM_Next */
pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
}
static Bool
ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
{
return TRUE;
}
static void
ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
{
ASTRecPtr pAST = ASTPTR(pScrn);
UCHAR *pjDstXor, *pjSrcXor;
ULONG i, j, ulSrcWidth, ulSrcHeight;
ULONG ulPerPixelCopy, ulTwoPixelCopy;
LONG lAlphaDstDelta, lLastAlphaDstDelta;
union
{
ULONG ul;
UCHAR b[4];
} ulSrcData32[2], ulData32;
union
{
USHORT us;
UCHAR b[2];
} usData16;
ULONG ulCheckSum = 0;
ULONG ulPatternAddr;
/* init cursor info. */
pAST->HWCInfo.cursortype = HWC_COLOR;
pAST->HWCInfo.width = pCurs->bits->width;
pAST->HWCInfo.height = pCurs->bits->height;
pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
/* copy cursor image to cache */
ulSrcWidth = pAST->HWCInfo.width;
ulSrcHeight = pAST->HWCInfo.height;
lAlphaDstDelta = MAX_HWC_WIDTH << 1;
lLastAlphaDstDelta = lAlphaDstDelta - (ulSrcWidth << 1);
pjSrcXor = (UCHAR *) pCurs->bits->argb;;
pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next
+ lLastAlphaDstDelta + (MAX_HWC_HEIGHT - ulSrcHeight) * lAlphaDstDelta;
ulPerPixelCopy = ulSrcWidth & 1;
ulTwoPixelCopy = ulSrcWidth >> 1;
for (j = 0; j < ulSrcHeight; j++)
{
for (i = 0; i < ulTwoPixelCopy; i++ )
{
ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
ulSrcData32[1].ul = *((ULONG *) (pjSrcXor+4)) & 0xF0F0F0F0;
ulData32.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
ulData32.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
ulData32.b[2] = ulSrcData32[1].b[1] | (ulSrcData32[1].b[0] >> 4);
ulData32.b[3] = ulSrcData32[1].b[3] | (ulSrcData32[1].b[2] >> 4);
*((ULONG *) pjDstXor) = ulData32.ul;
ulCheckSum += (ULONG) ulData32.ul;
pjDstXor += 4;
pjSrcXor += 8;
}
for (i = 0; i < ulPerPixelCopy; i++ )
{
ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
usData16.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
usData16.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
*((USHORT *) pjDstXor) = usData16.us;
ulCheckSum += (ULONG) usData16.us;
pjDstXor += 2;
pjSrcXor += 4;
}
/* Point to next source and dest scans */
pjDstXor += lLastAlphaDstDelta;
} /* end of for-loop */
/* Write Checksum as signature */
pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
*((ULONG *) pjDstXor) = ulCheckSum;
*((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
*((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
*((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTX)) = 0;
*((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTY)) = 0;
/* set pattern offset */
ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr +(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
/* update HWC_NUM_Next */
pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
}
static Bool
ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
{
return TRUE;
}
static void
ASTFireCursor(ScrnInfoPtr pScrn)
{
ASTRecPtr pAST = ASTPTR(pScrn);
SetIndexRegMask(CRTC_PORT, 0xCB, 0xFF, 0x00); /* dummp write to fire HWC */
}
#endif /* End of HWC */