mirror of
https://github.com/X11Libre/xf86-video-sis.git
synced 2026-03-24 01:25:01 +00:00
It's always enabled, so no need to have the code cluttered with those #ifdef's. Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
1396 lines
37 KiB
C
1396 lines
37 KiB
C
/*
|
|
* SiS hardware cursor handling
|
|
*
|
|
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1) Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2) Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3) The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Author: Thomas Winischhofer <thomas@winischhofer.net>
|
|
*
|
|
* Idea based on code by Can-Ru Yeou, SiS Inc.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "sis.h"
|
|
|
|
#include "cursorstr.h"
|
|
|
|
#define SIS_NEED_inSISREG
|
|
#define SIS_NEED_outSISREG
|
|
#define SIS_NEED_inSISIDXREG
|
|
#define SIS_NEED_outSISIDXREG
|
|
#define SIS_NEED_orSISIDXREG
|
|
#define SIS_NEED_andSISIDXREG
|
|
#define SIS_NEED_MYMMIO
|
|
#define SIS_NEED_MYFBACCESS
|
|
#include "sis_regs.h"
|
|
#include "sis_cursor.h"
|
|
|
|
extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn);
|
|
extern void SISWaitRetraceCRT2(ScrnInfoPtr pScrn);
|
|
|
|
/* Helper function for Xabre to convert mono image to ARGB */
|
|
/* The Xabre's cursor engine for CRT2 is buggy and can't
|
|
* handle mono cursors. We therefore convert the mono image
|
|
* to ARGB
|
|
*/
|
|
static void
|
|
SiSXConvertMono2ARGB(SISPtr pSiS)
|
|
{
|
|
UChar *src = pSiS->CurMonoSrc;
|
|
CARD32 *dest = pSiS->CurARGBDest;
|
|
CARD8 chunk, mask;
|
|
CARD32 fg = pSiS->CurFGCol | 0xff000000;
|
|
CARD32 bg = pSiS->CurBGCol | 0xff000000;
|
|
int i,j,k;
|
|
|
|
if(!dest || !src) return;
|
|
|
|
for(i = 0; i < 64; i++) {
|
|
for(j = 0; j < 8; j++) {
|
|
chunk = sisfbreadb(src + 8); /* *(src + 8); */
|
|
mask = sisfbreadbinc(src); /* *src++; */
|
|
for(k = 128; k != 0; k >>= 1) {
|
|
if(mask & k) sisfbwritelinc(dest, 0x00000000); /* *dest++ = 0x00000000; */
|
|
else if(chunk & k) sisfbwritelinc(dest, fg); /* *dest++ = fg; */
|
|
else sisfbwritelinc(dest, bg); /* *dest++ = bg; */
|
|
}
|
|
}
|
|
src += 8;
|
|
}
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
static void
|
|
UpdateHWCursorStatus(SISPtr pSiS)
|
|
{
|
|
int i, offs = 0;
|
|
|
|
if(pSiS->SecondHead) offs = 8;
|
|
|
|
for(i = 0; i < 8; i++) {
|
|
pSiS->HWCursorBackup[offs + i] = SIS_MMIO_IN32(pSiS->IOBase, 0x8500 + ((offs + i) << 2));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
SiSHideCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar sridx, cridx;
|
|
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
|
|
andSISIDXREG(SISSR, 0x06, 0xBF);
|
|
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
}
|
|
|
|
static void
|
|
SiS300HideCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode && (!pSiS->ForceCursorOff)) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis300DisableHWCursor()
|
|
sis300SetCursorPositionY(2000, 0)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
sis301DisableHWCursor()
|
|
sis301SetCursorPositionY(2000, 0)
|
|
}
|
|
} else {
|
|
#endif
|
|
sis300DisableHWCursor()
|
|
sis300SetCursorPositionY(2000, 0)
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301DisableHWCursor()
|
|
sis301SetCursorPositionY(2000, 0)
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiS310HideCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
pSiS->HWCursorIsVisible = FALSE;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode && (!pSiS->ForceCursorOff)) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis310DisableHWCursor()
|
|
sis310SetCursorPositionY(2000, 0)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
sis301DisableHWCursor310()
|
|
sis301SetCursorPositionY310(2000, 0)
|
|
}
|
|
} else {
|
|
#endif
|
|
sis310DisableHWCursor()
|
|
sis310SetCursorPositionY(2000, 0)
|
|
if(pSiS->VBFlags2 & VB2_VIDEOBRIDGE) {
|
|
sis301DisableHWCursor310()
|
|
sis301SetCursorPositionY310(2000, 0)
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiSShowCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar sridx, cridx;
|
|
|
|
/* Backup current indices of SR and CR since we run async:ly
|
|
* and might be interrupting an on-going register read/write
|
|
*/
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
|
|
orSISIDXREG(SISSR, 0x06, 0x40);
|
|
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
}
|
|
|
|
static void
|
|
SiS300ShowCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis300EnableHWARGBCursor()
|
|
} else {
|
|
sis300EnableHWCursor()
|
|
}
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis301EnableHWARGBCursor()
|
|
} else {
|
|
sis301EnableHWCursor()
|
|
}
|
|
}
|
|
} else {
|
|
#endif
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis300EnableHWARGBCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301EnableHWARGBCursor()
|
|
}
|
|
} else {
|
|
sis300EnableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301EnableHWCursor()
|
|
}
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiS310ShowCursor(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
if(pSiS->HideHWCursor) {
|
|
SiS310HideCursor(pScrn);
|
|
pSiS->HWCursorIsVisible = TRUE;
|
|
return;
|
|
}
|
|
|
|
pSiS->HWCursorIsVisible = TRUE;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis310EnableHWARGBCursor()
|
|
} else {
|
|
sis310EnableHWCursor()
|
|
}
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
sis301EnableHWCursor330()
|
|
} else {
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis301EnableHWARGBCursor310()
|
|
} else {
|
|
sis301EnableHWCursor310()
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
#endif
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis310EnableHWARGBCursor()
|
|
} else {
|
|
sis310EnableHWCursor()
|
|
}
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301EnableHWCursor330()
|
|
}
|
|
} else {
|
|
if(pSiS->UseHWARGBCursor) {
|
|
sis310EnableHWARGBCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301EnableHWARGBCursor310()
|
|
}
|
|
} else {
|
|
sis310EnableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301EnableHWCursor310()
|
|
}
|
|
}
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
UChar x_preset = 0;
|
|
UChar y_preset = 0;
|
|
int temp;
|
|
UChar sridx, cridx;
|
|
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
|
|
if(x < 0) {
|
|
x_preset = (-x);
|
|
x = 0;
|
|
}
|
|
|
|
if(y < 0) {
|
|
y_preset = (-y);
|
|
y = 0;
|
|
}
|
|
|
|
if(mode->Flags & V_INTERLACE) y /= 2;
|
|
else if(mode->Flags & V_DBLSCAN) y *= 2;
|
|
|
|
outSISIDXREG(SISSR, 0x1A, x & 0xff);
|
|
outSISIDXREG(SISSR, 0x1B, (x & 0xff00) >> 8);
|
|
outSISIDXREG(SISSR, 0x1D, y & 0xff);
|
|
|
|
inSISIDXREG(SISSR, 0x1E, temp);
|
|
temp &= 0xF8;
|
|
outSISIDXREG(SISSR, 0x1E, temp | ((y >> 8) & 0x07));
|
|
|
|
outSISIDXREG(SISSR, 0x1C, x_preset);
|
|
outSISIDXREG(SISSR, 0x1F, y_preset);
|
|
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
}
|
|
|
|
static void
|
|
SiSSetCursorPositionMerged(ScrnInfoPtr pScrn1, int x, int y)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn1);
|
|
ScrnInfoPtr pScrn2 = pSiS->CRT2pScrn;
|
|
DisplayModePtr mode1 = CDMPTR->CRT1;
|
|
DisplayModePtr mode2 = CDMPTR->CRT2;
|
|
UShort x1_preset = 0, x2_preset = 0;
|
|
UShort y1_preset = 0, y2_preset = 0;
|
|
UShort maxpreset;
|
|
int x1, y1, x2, y2;
|
|
|
|
x += pScrn1->frameX0;
|
|
y += pScrn1->frameY0;
|
|
|
|
x1 = x - pSiS->CRT1frameX0;
|
|
y1 = y - pSiS->CRT1frameY0;
|
|
|
|
x2 = x - pScrn2->frameX0;
|
|
y2 = y - pScrn2->frameY0;
|
|
|
|
maxpreset = 63;
|
|
if((pSiS->VGAEngine == SIS_300_VGA) && (pSiS->UseHWARGBCursor)) maxpreset = 31;
|
|
|
|
if(x1 < 0) {
|
|
x1_preset = (-x1);
|
|
if(x1_preset > maxpreset) x1_preset = maxpreset;
|
|
x1 = 0;
|
|
}
|
|
if(y1 < 0) {
|
|
y1_preset = (-y1);
|
|
if(y1_preset > maxpreset) y1_preset = maxpreset;
|
|
y1 = 0;
|
|
}
|
|
if(x2 < 0) {
|
|
x2_preset = (-x2);
|
|
if(x2_preset > maxpreset) x2_preset = maxpreset;
|
|
x2 = 0;
|
|
}
|
|
if(y2 < 0) {
|
|
y2_preset = (-y2);
|
|
if(y2_preset > maxpreset) y2_preset = maxpreset;
|
|
y2 = 0;
|
|
}
|
|
|
|
/* Work around bug in cursor engine if y > display */
|
|
if(y1 > mode1->VDisplay) { y1 = 2000; y1_preset = 0; }
|
|
else if(mode1->Flags & V_INTERLACE) { y1 /= 2; y1_preset /= 2; }
|
|
else if(mode1->Flags & V_DBLSCAN) { y1 *= 2; y1_preset *= 2; }
|
|
|
|
if(y2 > mode2->VDisplay) { y2 = 2000; y2_preset = 0; }
|
|
else if(mode2->Flags & V_INTERLACE) { y2 /= 2; y2_preset /= 2; }
|
|
else if(mode2->Flags & V_DBLSCAN) { y2 *= 2; y2_preset *= 2; }
|
|
|
|
/* Work around bug in cursor engine if x > display */
|
|
if(x1 > mode1->HDisplay) { y1 = 2000; y1_preset = 0; }
|
|
if(x2 > mode2->HDisplay) { y2 = 2000; y2_preset = 0; }
|
|
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
sis300SetCursorPositionX(x1, x1_preset)
|
|
sis300SetCursorPositionY(y1, y1_preset)
|
|
sis301SetCursorPositionX(x2 + 13, x2_preset)
|
|
sis301SetCursorPositionY(y2, y2_preset)
|
|
} else {
|
|
sis310SetCursorPositionX(x1, x1_preset)
|
|
sis310SetCursorPositionY(y1, y1_preset)
|
|
sis301SetCursorPositionX310(x2 + 17, x2_preset)
|
|
sis301SetCursorPositionY310(y2, y2_preset)
|
|
}
|
|
}
|
|
|
|
static void
|
|
SiS300SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode; /* pScrn->currentMode; */
|
|
UShort x_preset = 0;
|
|
UShort y_preset = 0;
|
|
|
|
if(pSiS->MergedFB) {
|
|
SiSSetCursorPositionMerged(pScrn, x, y);
|
|
return;
|
|
}
|
|
|
|
if(mode->Flags & V_INTERLACE) y /= 2;
|
|
else if(mode->Flags & V_DBLSCAN) y *= 2;
|
|
|
|
if(x < 0) {
|
|
x_preset = (-x);
|
|
x = 0;
|
|
}
|
|
if(y < 0) {
|
|
y_preset = (-y);
|
|
y = 0;
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis300SetCursorPositionX(x, x_preset)
|
|
sis300SetCursorPositionY(y, y_preset)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
sis301SetCursorPositionX(x + 13, x_preset)
|
|
sis301SetCursorPositionY(y, y_preset)
|
|
}
|
|
} else {
|
|
#endif
|
|
sis300SetCursorPositionX(x, x_preset)
|
|
sis300SetCursorPositionY(y, y_preset)
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301SetCursorPositionX(x + 13, x_preset)
|
|
sis301SetCursorPositionY(y, y_preset)
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiS310SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
UShort x_preset = 0;
|
|
UShort y_preset = 0;
|
|
|
|
if(pSiS->MergedFB) {
|
|
SiSSetCursorPositionMerged(pScrn, x, y);
|
|
return;
|
|
}
|
|
|
|
if(mode->Flags & V_INTERLACE) y >>= 1;
|
|
else if(mode->Flags & V_DBLSCAN) y <<= 1;
|
|
|
|
if(x < 0) {
|
|
x_preset = (-x);
|
|
x = 0;
|
|
}
|
|
if(y < 0) {
|
|
y_preset = (-y);
|
|
y = 0;
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis310SetCursorPositionX(x, x_preset)
|
|
sis310SetCursorPositionY(y, y_preset)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
#if 0
|
|
if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) {
|
|
y >>= 1;
|
|
y_preset >>= 1;
|
|
}
|
|
#endif
|
|
sis301SetCursorPositionX310(x + 17, x_preset)
|
|
sis301SetCursorPositionY310(y, y_preset)
|
|
}
|
|
} else {
|
|
#endif
|
|
sis310SetCursorPositionX(x, x_preset)
|
|
sis310SetCursorPositionY(y, y_preset)
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
#if 0
|
|
if((pSiS->VBFlags & CRT2_LCD) && (pSiS->FSTN || pSiS->DSTN)) {
|
|
y >>= 1;
|
|
y_preset >>= 1;
|
|
}
|
|
#endif
|
|
sis301SetCursorPositionX310(x + 17, x_preset)
|
|
sis301SetCursorPositionY310(y, y_preset)
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar f_red, f_green, f_blue;
|
|
UChar b_red, b_green, b_blue;
|
|
UChar sridx, cridx;
|
|
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
|
|
f_red = (fg & 0x00FF0000) >> (16+2);
|
|
f_green = (fg & 0x0000FF00) >> (8+2);
|
|
f_blue = (fg & 0x000000FF) >> 2;
|
|
b_red = (bg & 0x00FF0000) >> (16+2);
|
|
b_green = (bg & 0x0000FF00) >> (8+2);
|
|
b_blue = (bg & 0x000000FF) >> 2;
|
|
|
|
outSISIDXREG(SISSR, 0x14, b_red);
|
|
outSISIDXREG(SISSR, 0x15, b_green);
|
|
outSISIDXREG(SISSR, 0x16, b_blue);
|
|
outSISIDXREG(SISSR, 0x17, f_red);
|
|
outSISIDXREG(SISSR, 0x18, f_green);
|
|
outSISIDXREG(SISSR, 0x19, f_blue);
|
|
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
}
|
|
|
|
static void
|
|
SiS300SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
if(pSiS->UseHWARGBCursor) return;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis300SetCursorBGColor(bg)
|
|
sis300SetCursorFGColor(fg)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
sis301SetCursorBGColor(bg)
|
|
sis301SetCursorFGColor(fg)
|
|
}
|
|
} else {
|
|
#endif
|
|
sis300SetCursorBGColor(bg)
|
|
sis300SetCursorFGColor(fg)
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
sis301SetCursorBGColor(bg)
|
|
sis301SetCursorFGColor(fg)
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiS310SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
|
|
if(pSiS->UseHWARGBCursor) return;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
if(pSiS->SecondHead) {
|
|
/* Head 2 is always CRT1 */
|
|
sis310SetCursorBGColor(bg)
|
|
sis310SetCursorFGColor(fg)
|
|
} else {
|
|
/* Head 1 is always CRT2 */
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
if((fg != pSiS->CurFGCol) || (bg != pSiS->CurBGCol)) {
|
|
pSiS->CurFGCol = fg;
|
|
pSiS->CurBGCol = bg;
|
|
SiSXConvertMono2ARGB(pSiS);
|
|
}
|
|
} else {
|
|
sis301SetCursorBGColor310(bg)
|
|
sis301SetCursorFGColor310(fg)
|
|
}
|
|
}
|
|
} else {
|
|
#endif
|
|
sis310SetCursorBGColor(bg)
|
|
sis310SetCursorFGColor(fg)
|
|
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
if((fg != pSiS->CurFGCol) || (bg != pSiS->CurBGCol)) {
|
|
pSiS->CurFGCol = fg;
|
|
pSiS->CurBGCol = bg;
|
|
SiSXConvertMono2ARGB(pSiS);
|
|
}
|
|
} else {
|
|
sis301SetCursorBGColor310(bg)
|
|
sis301SetCursorFGColor310(fg)
|
|
}
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SiSLoadCursorImage(ScrnInfoPtr pScrn, UChar *src)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
ULong cursor_addr;
|
|
UChar temp;
|
|
UChar sridx, cridx;
|
|
|
|
sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
|
|
|
|
sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
|
|
|
|
cursor_addr = pScrn->videoRam - 1;
|
|
if(mode->Flags & V_DBLSCAN) {
|
|
int i;
|
|
for(i = 0; i < 32; i++) {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)pSiS->RealFbBase + (cursor_addr * 1024) + (32 * i),
|
|
src + (16 * i), 16);
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)pSiS->RealFbBase + (cursor_addr * 1024) + (32 * i) + 16,
|
|
src + (16 * i), 16);
|
|
}
|
|
} else {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)pSiS->RealFbBase + (cursor_addr * 1024), src, 1024);
|
|
}
|
|
|
|
/* copy bits [21:18] into the top bits of SR38 */
|
|
inSISIDXREG(SISSR, 0x38, temp);
|
|
temp &= 0x0F;
|
|
outSISIDXREG(SISSR, 0x38, temp | ((cursor_addr & 0xF00) >> 4));
|
|
|
|
if(pSiS->Chipset == PCI_CHIP_SIS530) {
|
|
/* store the bit [22] to SR3E */
|
|
if(cursor_addr & 0x1000) {
|
|
orSISIDXREG(SISSR, 0x3E, 0x04);
|
|
} else {
|
|
andSISIDXREG(SISSR, 0x3E, ~0x04);
|
|
}
|
|
}
|
|
|
|
/* set HW cursor pattern, use pattern 0xF */
|
|
orSISIDXREG(SISSR, 0x1E, 0xF0);
|
|
|
|
/* disable the hardware cursor side pattern */
|
|
andSISIDXREG(SISSR, 0x1E, 0xF7);
|
|
|
|
outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
|
|
}
|
|
|
|
static void
|
|
SiS300LoadCursorImage(ScrnInfoPtr pScrn, UChar *src)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
ULong cursor_addr;
|
|
CARD32 status1 = 0, status2 = 0;
|
|
UChar *dest = pSiS->RealFbBase;
|
|
Bool sizedouble = FALSE;
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
#endif
|
|
|
|
if(pSiS->MergedFB) {
|
|
if((CDMPTR->CRT1->Flags & V_DBLSCAN) && (CDMPTR->CRT2->Flags & V_DBLSCAN)) {
|
|
sizedouble = TRUE;
|
|
}
|
|
} else if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) {
|
|
sizedouble = TRUE;
|
|
}
|
|
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - (pSiS->CursorSize/1024); /* 1K boundary */
|
|
|
|
#ifdef SISDUALHEAD
|
|
/* Use the global FbBase in DHM */
|
|
if(pSiS->DualHeadMode) dest = pSiSEnt->RealFbBase;
|
|
#endif
|
|
|
|
if(sizedouble) {
|
|
int i;
|
|
for(i = 0; i < 32; i++) {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024) + (32 * i),
|
|
src + (16 * i), 16);
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024) + (32 * i) + 16,
|
|
src + (16 * i), 16);
|
|
}
|
|
} else {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024), src, 1024);
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
UpdateHWCursorStatus(pSiS);
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis300GetCursorStatus;
|
|
sis300DisableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
status2 = sis301GetCursorStatus;
|
|
sis301DisableHWCursor()
|
|
}
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis300SwitchToMONOCursor();
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToMONOCursor();
|
|
}
|
|
}
|
|
}
|
|
sis300SetCursorAddress(cursor_addr);
|
|
if(status1) {
|
|
sis300SetCursorStatus(status1)
|
|
}
|
|
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
if((pSiS->UseHWARGBCursor) && (!(pSiS->VBFlags & DISPTYPE_CRT1))) {
|
|
status2 = sis301GetCursorStatus;
|
|
sis301DisableHWCursor()
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToMONOCursor();
|
|
}
|
|
sis301SetCursorAddress(cursor_addr)
|
|
if(status2) {
|
|
sis301SetCursorStatus(status2)
|
|
}
|
|
}
|
|
|
|
pSiS->UseHWARGBCursor = FALSE;
|
|
}
|
|
|
|
static void
|
|
SiS310LoadCursorImage(ScrnInfoPtr pScrn, UChar *src)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
ULong cursor_addr, cursor_addr2 = 0;
|
|
CARD32 status1 = 0, status2 = 0;
|
|
UChar *dest = pSiS->RealFbBase;
|
|
Bool sizedouble = FALSE;
|
|
int bufnum;
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
|
|
if(pSiS->DualHeadMode) {
|
|
pSiSEnt->HWCursorMBufNum ^= 1;
|
|
bufnum = 1 << pSiSEnt->HWCursorMBufNum;
|
|
} else {
|
|
#endif
|
|
pSiS->HWCursorMBufNum ^= 1;
|
|
bufnum = 1 << pSiS->HWCursorMBufNum;
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->MergedFB) {
|
|
if((CDMPTR->CRT1->Flags & V_DBLSCAN) && (CDMPTR->CRT2->Flags & V_DBLSCAN)) {
|
|
sizedouble = TRUE;
|
|
}
|
|
} else if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) {
|
|
sizedouble = TRUE;
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
/* Use the global FbBase in DHM */
|
|
if(pSiS->DualHeadMode) dest = pSiSEnt->RealFbBase;
|
|
#endif
|
|
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - (pSiS->CursorSize/1024);
|
|
} else {
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * bufnum);
|
|
}
|
|
|
|
if(sizedouble) {
|
|
int i;
|
|
for(i = 0; i < 32; i++) {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024) + (32 * i),
|
|
src + (16 * i), 16);
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024) + (32 * i) + 16,
|
|
src + (16 * i), 16);
|
|
}
|
|
} else {
|
|
SiSMemCopyToVideoRam(pSiS, (UChar *)dest + (cursor_addr * 1024), src, 1024);
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
UpdateHWCursorStatus(pSiS);
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
|
|
/* Convert Mono image to color image */
|
|
cursor_addr2 = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * 2);
|
|
|
|
pSiS->CurMonoSrc = (UChar *)dest + (cursor_addr * 1024);
|
|
pSiS->CurARGBDest = (CARD32 *)((UChar *)dest + (cursor_addr2 * 1024));
|
|
|
|
SiSXConvertMono2ARGB(pSiS);
|
|
|
|
if(pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis310GetCursorStatus;
|
|
sis310DisableHWCursor();
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis310SwitchToMONOCursor();
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
if(pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis310GetCursorStatus;
|
|
sis310DisableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
status2 = sis301GetCursorStatus310;
|
|
sis301DisableHWCursor310()
|
|
}
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis310SwitchToMONOCursor();
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToMONOCursor310();
|
|
}
|
|
}
|
|
} else if(pSiS->Chipset == PCI_CHIP_SIS315H) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
SISWaitRetraceCRT1(pScrn);
|
|
}
|
|
}
|
|
}
|
|
|
|
sis310SetCursorAddress(cursor_addr);
|
|
if(status1) {
|
|
sis310SetCursorStatus(status1)
|
|
}
|
|
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
sis301SetCursorAddress310(cursor_addr2)
|
|
} else {
|
|
if((pSiS->UseHWARGBCursor) && (!(pSiS->VBFlags & DISPTYPE_CRT1))) {
|
|
status2 = sis301GetCursorStatus310;
|
|
sis301DisableHWCursor310()
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToMONOCursor310();
|
|
}
|
|
sis301SetCursorAddress310(cursor_addr)
|
|
if(status2) {
|
|
sis301SetCursorStatus310(status2)
|
|
}
|
|
}
|
|
}
|
|
|
|
pSiS->UseHWARGBCursor = FALSE;
|
|
}
|
|
|
|
static Bool
|
|
SiSUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
|
|
if(pSiS->Chipset != PCI_CHIP_SIS6326) return TRUE;
|
|
if(!(pSiS->SiS6326Flags & SIS6326_TVDETECTED)) return TRUE;
|
|
if((strcmp(mode->name, "PAL800x600U") == 0) ||
|
|
(strcmp(mode->name, "NTSC640x480U") == 0))
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
SiS300UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
DisplayModePtr mode2 = NULL;
|
|
|
|
if(pSiS->MergedFB) {
|
|
mode = CDMPTR->CRT1;
|
|
mode2 = CDMPTR->CRT2;
|
|
}
|
|
|
|
switch (pSiS->Chipset) {
|
|
case PCI_CHIP_SIS300:
|
|
case PCI_CHIP_SIS630:
|
|
case PCI_CHIP_SIS540:
|
|
if(mode->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
if(pSiS->MergedFB) {
|
|
if(mode2->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode2->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PCI_CHIP_SIS550:
|
|
#ifdef SISDUALHEAD
|
|
if((!pSiS->DualHeadMode) || (!pSiS->SecondHead))
|
|
#endif
|
|
if((pSiS->FSTN || pSiS->DSTN) && (pSiS->VBFlags & CRT2_LCD))
|
|
return FALSE;
|
|
/* fall through */
|
|
case PCI_CHIP_SIS315:
|
|
case PCI_CHIP_SIS315H:
|
|
case PCI_CHIP_SIS315PRO:
|
|
case PCI_CHIP_SIS650:
|
|
case PCI_CHIP_SIS330:
|
|
case PCI_CHIP_SIS660:
|
|
case PCI_CHIP_SIS340:
|
|
case PCI_CHIP_XGIXG20:
|
|
case PCI_CHIP_XGIXG40:
|
|
if(mode->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
if(pSiS->MergedFB) {
|
|
if(mode2->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode2->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if(mode->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
SiSUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
DisplayModePtr mode = pSiS->CurrentLayout.mode;
|
|
DisplayModePtr mode2 = NULL;
|
|
|
|
if(pSiS->MergedFB) {
|
|
mode = CDMPTR->CRT1;
|
|
mode2 = CDMPTR->CRT2;
|
|
}
|
|
|
|
switch (pSiS->Chipset) {
|
|
case PCI_CHIP_SIS300:
|
|
case PCI_CHIP_SIS630:
|
|
case PCI_CHIP_SIS540:
|
|
if(mode->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((pCurs->bits->height > 32) || (pCurs->bits->width > 32))
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 16))
|
|
return FALSE;
|
|
if(pSiS->MergedFB) {
|
|
if(mode2->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode2->Flags & V_DBLSCAN) && (pCurs->bits->height > 16))
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case PCI_CHIP_SIS550:
|
|
#ifdef SISDUALHEAD
|
|
if((!pSiS->DualHeadMode) || (!pSiS->SecondHead))
|
|
#endif
|
|
if((pSiS->FSTN || pSiS->DSTN) && (pSiS->VBFlags & CRT2_LCD))
|
|
return FALSE;
|
|
/* fall through */
|
|
case PCI_CHIP_SIS650:
|
|
case PCI_CHIP_SIS315:
|
|
case PCI_CHIP_SIS315H:
|
|
case PCI_CHIP_SIS315PRO:
|
|
case PCI_CHIP_SIS330:
|
|
case PCI_CHIP_SIS660:
|
|
case PCI_CHIP_SIS340:
|
|
case PCI_CHIP_XGIXG20:
|
|
case PCI_CHIP_XGIXG40:
|
|
if(mode->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((pCurs->bits->height > 64) || (pCurs->bits->width > 64))
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
if((pSiS->CurrentLayout.bitsPerPixel == 8) && (pSiS->VBFlags & CRT2_ENABLE))
|
|
return FALSE;
|
|
if(pSiS->MergedFB) {
|
|
if(mode2->Flags & V_INTERLACE)
|
|
return FALSE;
|
|
if((mode->Flags & V_DBLSCAN) && (pCurs->bits->height > 32))
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
SiS300LoadCursorImageARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int cursor_addr, i, j, maxheight = 32;
|
|
CARD32 *src = pCurs->bits->argb, *p;
|
|
CARD32 *pb, *dest;
|
|
#define MYSISPTRTYPE CARD32
|
|
int srcwidth = pCurs->bits->width;
|
|
int srcheight = pCurs->bits->height;
|
|
CARD32 temp, status1 = 0, status2 = 0;
|
|
Bool sizedouble = FALSE;
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
#endif
|
|
|
|
if(pSiS->MergedFB) {
|
|
if((CDMPTR->CRT1->Flags & V_DBLSCAN) && (CDMPTR->CRT2->Flags & V_DBLSCAN)) {
|
|
sizedouble = TRUE;
|
|
}
|
|
} else if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) {
|
|
sizedouble = TRUE;
|
|
}
|
|
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * 2);
|
|
|
|
if(srcwidth > 32) srcwidth = 32;
|
|
if(srcheight > 32) srcheight = 32;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if (pSiS->DualHeadMode)
|
|
dest = (MYSISPTRTYPE *)((UChar *)pSiSEnt->RealFbBase + (cursor_addr * 1024));
|
|
else
|
|
#endif
|
|
dest = (MYSISPTRTYPE *)((UChar *)pSiS->RealFbBase + (cursor_addr * 1024));
|
|
|
|
if(sizedouble) {
|
|
if(srcheight > 16) srcheight = 16;
|
|
maxheight = 16;
|
|
}
|
|
|
|
for(i = 0; i < srcheight; i++) {
|
|
p = src;
|
|
pb = dest;
|
|
src += pCurs->bits->width;
|
|
for(j = 0; j < srcwidth; j++) {
|
|
temp = *p++;
|
|
if(pSiS->OptUseColorCursorBlend) {
|
|
if(temp & 0xffffff) {
|
|
if((temp & 0xff000000) > pSiS->OptColorCursorBlendThreshold) {
|
|
temp &= 0x00ffffff;
|
|
} else {
|
|
temp = 0xff111111;
|
|
}
|
|
} else temp = 0xff000000;
|
|
} else {
|
|
if(temp & 0xffffff) temp &= 0x00ffffff;
|
|
else temp = 0xff000000;
|
|
}
|
|
sisfbwritelinc(dest, temp); /* *dest++ = temp; */
|
|
}
|
|
if(srcwidth < 32) {
|
|
for(; j < 32; j++) {
|
|
sisfbwritelinc(dest, 0xff000000); /* *dest++ = 0xff000000; */
|
|
}
|
|
}
|
|
if(sizedouble) {
|
|
for(j = 0; j < 32; j++) {
|
|
sisfbwritelinc(dest, sisfbreadlinc(pb)); /* *dest++ = *pb++; */
|
|
}
|
|
}
|
|
|
|
}
|
|
if(srcheight < maxheight) {
|
|
for(; i < maxheight; i++) {
|
|
for(j = 0; j < 32; j++) {
|
|
sisfbwritelinc(dest, 0xff000000); /* *dest++ = 0xff000000; */
|
|
}
|
|
if(sizedouble) {
|
|
for(j = 0; j < 32; j++) {
|
|
sisfbwritelinc(dest, 0xff000000); /* *dest++ = 0xff000000; */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
UpdateHWCursorStatus(pSiS);
|
|
}
|
|
#endif
|
|
|
|
if(!pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis300GetCursorStatus;
|
|
sis300DisableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
status2 = sis301GetCursorStatus;
|
|
sis301DisableHWCursor()
|
|
}
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis300SwitchToRGBCursor();
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToRGBCursor();
|
|
}
|
|
}
|
|
}
|
|
|
|
sis300SetCursorAddress(cursor_addr);
|
|
if(status1) {
|
|
sis300SetCursorStatus(status1)
|
|
}
|
|
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
if((!pSiS->UseHWARGBCursor) && (!(pSiS->VBFlags & DISPTYPE_CRT1))) {
|
|
status2 = sis301GetCursorStatus;
|
|
sis301DisableHWCursor()
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToRGBCursor();
|
|
}
|
|
sis301SetCursorAddress(cursor_addr)
|
|
if(status2) {
|
|
sis301SetCursorStatus(status2)
|
|
}
|
|
}
|
|
|
|
pSiS->UseHWARGBCursor = TRUE;
|
|
}
|
|
|
|
static void SiS310LoadCursorImageARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int cursor_addr, i, j, maxheight = 64;
|
|
CARD32 *src = pCurs->bits->argb, *p, *pb, *dest;
|
|
int srcwidth = pCurs->bits->width;
|
|
int srcheight = pCurs->bits->height;
|
|
CARD32 status1 = 0, status2 = 0;
|
|
Bool sizedouble = FALSE;
|
|
int bufnum;
|
|
#ifdef SISDUALHEAD
|
|
SISEntPtr pSiSEnt = pSiS->entityPrivate;
|
|
#endif
|
|
|
|
if(pSiS->MergedFB) {
|
|
if((CDMPTR->CRT1->Flags & V_DBLSCAN) && (CDMPTR->CRT2->Flags & V_DBLSCAN)) {
|
|
sizedouble = TRUE;
|
|
}
|
|
} else if(pSiS->CurrentLayout.mode->Flags & V_DBLSCAN) {
|
|
sizedouble = TRUE;
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
pSiSEnt->HWCursorCBufNum ^= 1;
|
|
bufnum = 1 << pSiSEnt->HWCursorCBufNum;
|
|
} else {
|
|
#endif
|
|
pSiS->HWCursorCBufNum ^= 1;
|
|
bufnum = 1 << pSiS->HWCursorCBufNum;
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * 2);
|
|
} else {
|
|
cursor_addr = pScrn->videoRam - pSiS->cursorOffset - ((pSiS->CursorSize/1024) * (2 + bufnum));
|
|
}
|
|
|
|
if(srcwidth > 64) srcwidth = 64;
|
|
if(srcheight > 64) srcheight = 64;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode)
|
|
dest = (CARD32 *)((UChar *)pSiSEnt->RealFbBase + (cursor_addr * 1024));
|
|
else
|
|
#endif
|
|
dest = (CARD32 *)((UChar *)pSiS->RealFbBase + (cursor_addr * 1024));
|
|
|
|
if(sizedouble) {
|
|
if(srcheight > 32) srcheight = 32;
|
|
maxheight = 32;
|
|
}
|
|
|
|
for(i = 0; i < srcheight; i++) {
|
|
p = src;
|
|
pb = dest;
|
|
src += pCurs->bits->width;
|
|
for(j = 0; j < srcwidth; j++) sisfbwritelpinc(dest, p); /* *dest++ = *p++; */
|
|
if(srcwidth < 64) {
|
|
for(; j < 64; j++) sisfbwritelinc(dest, 0); /* *dest++ = 0; */
|
|
}
|
|
if(sizedouble) {
|
|
for(j = 0; j < 64; j++) {
|
|
sisfbwritelinc(dest, sisfbreadlinc(pb)); /* *dest++ = *pb++; */
|
|
}
|
|
}
|
|
}
|
|
if(srcheight < maxheight) {
|
|
for(; i < maxheight; i++) {
|
|
for(j = 0; j < 64; j++) sisfbwritelinc(dest, 0); /* *dest++ = 0; */
|
|
if(sizedouble) {
|
|
for(j = 0; j < 64; j++) sisfbwritelinc(dest, 0); /* *dest++ = 0; */
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
UpdateHWCursorStatus(pSiS);
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
if(!pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis310GetCursorStatus;
|
|
sis310DisableHWCursor()
|
|
}
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis310SwitchToRGBCursor();
|
|
}
|
|
} else {
|
|
if(!pSiS->UseHWARGBCursor) {
|
|
if(pSiS->VBFlags & DISPTYPE_CRT1) {
|
|
status1 = sis310GetCursorStatus;
|
|
sis310DisableHWCursor()
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
status2 = sis301GetCursorStatus310;
|
|
sis301DisableHWCursor310()
|
|
}
|
|
}
|
|
SISWaitRetraceCRT1(pScrn);
|
|
sis310SwitchToRGBCursor();
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToRGBCursor310();
|
|
}
|
|
}
|
|
}
|
|
|
|
sis310SetCursorAddress(cursor_addr);
|
|
if(status1) {
|
|
sis310SetCursorStatus(status1)
|
|
}
|
|
|
|
if(pSiS->VBFlags & CRT2_ENABLE) {
|
|
if(pSiS->ChipFlags & SiSCF_CRT2HWCKaputt) {
|
|
sis301SetCursorAddress310(cursor_addr)
|
|
} else {
|
|
if((!pSiS->UseHWARGBCursor) && (!(pSiS->VBFlags & DISPTYPE_CRT1))) {
|
|
status2 = sis301GetCursorStatus310;
|
|
sis301DisableHWCursor310()
|
|
SISWaitRetraceCRT2(pScrn);
|
|
sis301SwitchToRGBCursor310();
|
|
}
|
|
sis301SetCursorAddress310(cursor_addr)
|
|
if(status2) {
|
|
sis301SetCursorStatus310(status2)
|
|
}
|
|
}
|
|
}
|
|
|
|
pSiS->UseHWARGBCursor = TRUE;
|
|
}
|
|
|
|
Bool
|
|
SiSHWCursorInit(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
xf86CursorInfoPtr infoPtr;
|
|
|
|
infoPtr = xf86CreateCursorInfoRec();
|
|
if(!infoPtr) return FALSE;
|
|
|
|
pSiS->CursorInfoPtr = infoPtr;
|
|
pSiS->UseHWARGBCursor = FALSE;
|
|
|
|
switch(pSiS->Chipset) {
|
|
case PCI_CHIP_SIS300:
|
|
case PCI_CHIP_SIS630:
|
|
case PCI_CHIP_SIS540:
|
|
infoPtr->MaxWidth = 64;
|
|
infoPtr->MaxHeight = 64;
|
|
infoPtr->ShowCursor = SiS300ShowCursor;
|
|
infoPtr->HideCursor = SiS300HideCursor;
|
|
infoPtr->SetCursorPosition = SiS300SetCursorPosition;
|
|
infoPtr->SetCursorColors = SiS300SetCursorColors;
|
|
infoPtr->LoadCursorImage = SiS300LoadCursorImage;
|
|
infoPtr->UseHWCursor = SiS300UseHWCursor;
|
|
if(pSiS->OptUseColorCursor) {
|
|
infoPtr->UseHWCursorARGB = SiSUseHWCursorARGB;
|
|
infoPtr->LoadCursorARGB = SiS300LoadCursorImageARGB;
|
|
}
|
|
infoPtr->Flags =
|
|
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
|
|
HARDWARE_CURSOR_INVERT_MASK |
|
|
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
|
|
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
|
|
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
|
|
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
|
|
break;
|
|
|
|
case PCI_CHIP_SIS315:
|
|
case PCI_CHIP_SIS315H:
|
|
case PCI_CHIP_SIS315PRO:
|
|
case PCI_CHIP_SIS550:
|
|
case PCI_CHIP_SIS650:
|
|
case PCI_CHIP_SIS330:
|
|
case PCI_CHIP_SIS660:
|
|
case PCI_CHIP_SIS340:
|
|
case PCI_CHIP_XGIXG20:
|
|
case PCI_CHIP_XGIXG40:
|
|
infoPtr->MaxWidth = 64;
|
|
infoPtr->MaxHeight = 64;
|
|
infoPtr->ShowCursor = SiS310ShowCursor;
|
|
infoPtr->HideCursor = SiS310HideCursor;
|
|
infoPtr->SetCursorPosition = SiS310SetCursorPosition;
|
|
infoPtr->SetCursorColors = SiS310SetCursorColors;
|
|
infoPtr->LoadCursorImage = SiS310LoadCursorImage;
|
|
infoPtr->UseHWCursor = SiS300UseHWCursor;
|
|
if(pSiS->OptUseColorCursor) {
|
|
infoPtr->UseHWCursorARGB = SiSUseHWCursorARGB;
|
|
infoPtr->LoadCursorARGB = SiS310LoadCursorImageARGB;
|
|
}
|
|
infoPtr->Flags =
|
|
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
|
|
HARDWARE_CURSOR_INVERT_MASK |
|
|
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
|
|
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
|
|
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
|
|
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
|
|
break;
|
|
|
|
default:
|
|
infoPtr->MaxWidth = 64;
|
|
infoPtr->MaxHeight = 64;
|
|
infoPtr->SetCursorPosition = SiSSetCursorPosition;
|
|
infoPtr->ShowCursor = SiSShowCursor;
|
|
infoPtr->HideCursor = SiSHideCursor;
|
|
infoPtr->SetCursorColors = SiSSetCursorColors;
|
|
infoPtr->LoadCursorImage = SiSLoadCursorImage;
|
|
infoPtr->UseHWCursor = SiSUseHWCursor;
|
|
infoPtr->Flags =
|
|
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
|
|
HARDWARE_CURSOR_INVERT_MASK |
|
|
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
|
|
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
|
|
HARDWARE_CURSOR_NIBBLE_SWAPPED |
|
|
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
|
|
break;
|
|
}
|
|
|
|
return(xf86InitCursor(pScreen, infoPtr));
|
|
}
|