528 lines
14 KiB
C
528 lines
14 KiB
C
|
|
#ifdef HAVE_XORG_CONFIG_H
|
|
#include <xorg-config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "misc.h"
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
|
|
#include <X11/X.h>
|
|
#include "scrnintstr.h"
|
|
#include "pixmapstr.h"
|
|
#include "windowstr.h"
|
|
#include "xf86str.h"
|
|
#include "cursorstr.h"
|
|
#include "mi.h"
|
|
#include "mipointer.h"
|
|
#include "xf86CursorPriv.h"
|
|
|
|
#include "servermd.h"
|
|
|
|
#if BITMAP_SCANLINE_PAD == 64
|
|
|
|
#if 1
|
|
/* Cursors might be only 32 wide. Give'em a chance */
|
|
#define SCANLINE CARD32
|
|
#define CUR_BITMAP_SCANLINE_PAD 32
|
|
#define CUR_LOG2_BITMAP_PAD 5
|
|
#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
|
|
#else
|
|
#define SCANLINE CARD64
|
|
#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
|
|
#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
|
|
#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
|
|
static CARD64 xf86CARD64ReverseBits(CARD64 w);
|
|
|
|
static CARD64
|
|
xf86CARD64ReverseBits(CARD64 w)
|
|
{
|
|
unsigned char *p = (unsigned char *)&w;
|
|
|
|
p[0] = byte_reversed[p[0]];
|
|
p[1] = byte_reversed[p[1]];
|
|
p[2] = byte_reversed[p[2]];
|
|
p[3] = byte_reversed[p[3]];
|
|
p[4] = byte_reversed[p[4]];
|
|
p[5] = byte_reversed[p[5]];
|
|
p[6] = byte_reversed[p[6]];
|
|
p[7] = byte_reversed[p[7]];
|
|
|
|
return w;
|
|
}
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define SCANLINE CARD32
|
|
#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
|
|
#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
|
|
#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
|
|
|
|
#endif /* BITMAP_SCANLINE_PAD == 64 */
|
|
|
|
static unsigned char* RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
|
|
static unsigned char* RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
|
|
static unsigned char* RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
|
|
static unsigned char* RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
|
|
static unsigned char* RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
|
|
static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
|
|
|
|
Bool
|
|
xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
|
|
{
|
|
if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
|
|
return FALSE;
|
|
|
|
/* These are required for now */
|
|
if (!infoPtr->SetCursorPosition ||
|
|
!infoPtr->LoadCursorImage ||
|
|
!infoPtr->HideCursor ||
|
|
!infoPtr->ShowCursor ||
|
|
!infoPtr->SetCursorColors)
|
|
return FALSE;
|
|
|
|
if (infoPtr->RealizeCursor) {
|
|
/* Don't overwrite a driver provided Realize Cursor function */
|
|
} else
|
|
if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave1;
|
|
} else
|
|
if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave8;
|
|
} else
|
|
if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave16;
|
|
} else
|
|
if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave32;
|
|
} else
|
|
if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave64;
|
|
} else { /* not interleaved */
|
|
infoPtr->RealizeCursor = RealizeCursorInterleave0;
|
|
}
|
|
|
|
infoPtr->pScrn = xf86Screens[pScreen->myNum];
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
|
|
{
|
|
xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
|
|
&pScreen->devPrivates, xf86CursorScreenKey);
|
|
xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
|
|
unsigned char *bits;
|
|
|
|
if (pCurs == NullCursor) {
|
|
(*infoPtr->HideCursor)(infoPtr->pScrn);
|
|
return;
|
|
}
|
|
|
|
bits = dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen));
|
|
|
|
x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
|
|
y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
|
|
|
|
#ifdef ARGB_CURSOR
|
|
if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB)
|
|
#endif
|
|
if (!bits) {
|
|
bits = (*infoPtr->RealizeCursor)(infoPtr, pCurs);
|
|
dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), bits);
|
|
}
|
|
|
|
if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
|
|
(*infoPtr->HideCursor)(infoPtr->pScrn);
|
|
|
|
#ifdef ARGB_CURSOR
|
|
if (pCurs->bits->argb && infoPtr->LoadCursorARGB)
|
|
(*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs);
|
|
else
|
|
#endif
|
|
if (bits)
|
|
(*infoPtr->LoadCursorImage)(infoPtr->pScrn, bits);
|
|
|
|
xf86RecolorCursor(pScreen, pCurs, 1);
|
|
|
|
(*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y);
|
|
|
|
(*infoPtr->ShowCursor)(infoPtr->pScrn);
|
|
}
|
|
|
|
void
|
|
xf86SetTransparentCursor(ScreenPtr pScreen)
|
|
{
|
|
xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
|
|
&pScreen->devPrivates, xf86CursorScreenKey);
|
|
xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
|
|
|
|
if (!ScreenPriv->transparentData)
|
|
ScreenPriv->transparentData =
|
|
(*infoPtr->RealizeCursor)(infoPtr, NullCursor);
|
|
|
|
if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
|
|
(*infoPtr->HideCursor)(infoPtr->pScrn);
|
|
|
|
if (ScreenPriv->transparentData)
|
|
(*infoPtr->LoadCursorImage)(infoPtr->pScrn,
|
|
ScreenPriv->transparentData);
|
|
|
|
(*infoPtr->ShowCursor)(infoPtr->pScrn);
|
|
}
|
|
|
|
void
|
|
xf86MoveCursor(ScreenPtr pScreen, int x, int y)
|
|
{
|
|
xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
|
|
&pScreen->devPrivates, xf86CursorScreenKey);
|
|
xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
|
|
|
|
x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
|
|
y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
|
|
|
|
(*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y);
|
|
}
|
|
|
|
void
|
|
xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
|
|
{
|
|
xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
|
|
&pScreen->devPrivates, xf86CursorScreenKey);
|
|
xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
|
|
|
|
#ifdef ARGB_CURSOR
|
|
/* recoloring isn't applicable to ARGB cursors and drivers
|
|
shouldn't have to ignore SetCursorColors requests */
|
|
if (pCurs->bits->argb)
|
|
return;
|
|
#endif
|
|
|
|
if (ScreenPriv->PalettedCursor) {
|
|
xColorItem sourceColor, maskColor;
|
|
ColormapPtr pmap = ScreenPriv->pInstalledMap;
|
|
|
|
if (!pmap)
|
|
return;
|
|
|
|
sourceColor.red = pCurs->foreRed;
|
|
sourceColor.green = pCurs->foreGreen;
|
|
sourceColor.blue = pCurs->foreBlue;
|
|
FakeAllocColor(pmap, &sourceColor);
|
|
maskColor.red = pCurs->backRed;
|
|
maskColor.green = pCurs->backGreen;
|
|
maskColor.blue = pCurs->backBlue;
|
|
FakeAllocColor(pmap, &maskColor);
|
|
FakeFreeColor(pmap, sourceColor.pixel);
|
|
FakeFreeColor(pmap, maskColor.pixel);
|
|
(*infoPtr->SetCursorColors)(infoPtr->pScrn,
|
|
maskColor.pixel, sourceColor.pixel);
|
|
} else { /* Pass colors in 8-8-8 RGB format */
|
|
(*infoPtr->SetCursorColors)(infoPtr->pScrn,
|
|
(pCurs->backBlue >> 8) |
|
|
((pCurs->backGreen >> 8) << 8) |
|
|
((pCurs->backRed >> 8) << 16),
|
|
(pCurs->foreBlue >> 8) |
|
|
((pCurs->foreGreen >> 8) << 8) |
|
|
((pCurs->foreRed >> 8) << 16)
|
|
);
|
|
}
|
|
}
|
|
|
|
/* These functions assume that MaxWidth is a multiple of 32 */
|
|
static unsigned char*
|
|
RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
|
|
SCANLINE *SrcS, *SrcM, *DstS, *DstM;
|
|
SCANLINE *pSrc, *pMsk;
|
|
unsigned char *mem;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
int SrcPitch, DstPitch, Pitch, y, x;
|
|
/* how many words are in the source or mask */
|
|
int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
|
|
|
|
|
|
if (!(mem = xcalloc(1, size)))
|
|
return NULL;
|
|
|
|
if (pCurs == NullCursor) {
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
|
|
DstM = (SCANLINE*)mem;
|
|
if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
|
|
DstM += words;
|
|
memset(DstM, -1, words * sizeof(SCANLINE));
|
|
}
|
|
return mem;
|
|
}
|
|
|
|
/* SrcPitch == the number of scanlines wide the cursor image is */
|
|
SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
|
|
CUR_LOG2_BITMAP_PAD;
|
|
|
|
/* DstPitch is the width of the hw cursor in scanlines */
|
|
DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
|
|
Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
|
|
|
|
SrcS = (SCANLINE*)pCurs->bits->source;
|
|
SrcM = (SCANLINE*)pCurs->bits->mask;
|
|
DstS = (SCANLINE*)mem;
|
|
DstM = DstS + words;
|
|
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
|
|
SCANLINE *tmp;
|
|
tmp = DstS; DstS = DstM; DstM = tmp;
|
|
}
|
|
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
|
|
for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
|
|
y--;
|
|
pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
|
|
for(x = 0; x < Pitch; x++) {
|
|
pSrc[x] = SrcS[x] & SrcM[x];
|
|
pMsk[x] = SrcM[x];
|
|
}
|
|
}
|
|
} else {
|
|
for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
|
|
y--;
|
|
pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
|
|
for(x = 0; x < Pitch; x++) {
|
|
pSrc[x] = SrcS[x];
|
|
pMsk[x] = SrcM[x];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
|
|
int count = size;
|
|
unsigned char* pntr1 = (unsigned char *)DstS;
|
|
unsigned char* pntr2 = (unsigned char *)DstM;
|
|
unsigned char a, b;
|
|
while (count) {
|
|
|
|
a = *pntr1;
|
|
b = *pntr2;
|
|
*pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
|
|
*pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
|
|
pntr1++; pntr2++;
|
|
count-=2;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
|
|
* out entire source mask.
|
|
*/
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
|
|
int count = words;
|
|
SCANLINE* pntr = DstM;
|
|
while (count--) {
|
|
*pntr = ~(*pntr);
|
|
pntr++;
|
|
}
|
|
}
|
|
|
|
if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
|
|
for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
|
|
y--;
|
|
pSrc+=DstPitch, pMsk+=DstPitch) {
|
|
for(x = 0; x < Pitch; x++) {
|
|
pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
|
|
pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return mem;
|
|
}
|
|
|
|
static unsigned char*
|
|
RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
unsigned char *DstS, *DstM;
|
|
unsigned char *pntr;
|
|
unsigned char *mem, *mem2;
|
|
int count;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
|
|
/* Realize the cursor without interleaving */
|
|
if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
|
|
return NULL;
|
|
|
|
if (!(mem = xcalloc(1, size))) {
|
|
xfree(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 1 bit interleave */
|
|
DstS = mem2;
|
|
DstM = DstS + (size >> 1);
|
|
pntr = mem;
|
|
count = size;
|
|
while (count) {
|
|
*pntr++ = ((*DstS&0x01) ) | ((*DstM&0x01) << 1) |
|
|
((*DstS&0x02) << 1) | ((*DstM&0x02) << 2) |
|
|
((*DstS&0x04) << 2) | ((*DstM&0x04) << 3) |
|
|
((*DstS&0x08) << 3) | ((*DstM&0x08) << 4);
|
|
*pntr++ = ((*DstS&0x10) >> 4) | ((*DstM&0x10) >> 3) |
|
|
((*DstS&0x20) >> 3) | ((*DstM&0x20) >> 2) |
|
|
((*DstS&0x40) >> 2) | ((*DstM&0x40) >> 1) |
|
|
((*DstS&0x80) >> 1) | ((*DstM&0x80) );
|
|
DstS++;
|
|
DstM++;
|
|
count-=2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
xfree(mem2);
|
|
|
|
return mem;
|
|
}
|
|
|
|
static unsigned char*
|
|
RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
unsigned char *DstS, *DstM;
|
|
unsigned char *pntr;
|
|
unsigned char *mem, *mem2;
|
|
int count;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
|
|
/* Realize the cursor without interleaving */
|
|
if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
|
|
return NULL;
|
|
|
|
if (!(mem = xcalloc(1, size))) {
|
|
xfree(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 8 bit interleave */
|
|
DstS = mem2;
|
|
DstM = DstS + (size >> 1);
|
|
pntr = mem;
|
|
count = size;
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
count-=2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
xfree(mem2);
|
|
|
|
return mem;
|
|
}
|
|
|
|
static unsigned char*
|
|
RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
unsigned short *DstS, *DstM;
|
|
unsigned short *pntr;
|
|
unsigned char *mem, *mem2;
|
|
int count;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
|
|
/* Realize the cursor without interleaving */
|
|
if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
|
|
return NULL;
|
|
|
|
if (!(mem = xcalloc(1, size))) {
|
|
xfree(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 16 bit interleave */
|
|
DstS = (pointer)mem2;
|
|
DstM = DstS + (size >> 2);
|
|
pntr = (pointer)mem;
|
|
count = (size >> 1);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
count-=2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
xfree(mem2);
|
|
|
|
return mem;
|
|
}
|
|
|
|
static unsigned char*
|
|
RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
CARD32 *DstS, *DstM;
|
|
CARD32 *pntr;
|
|
unsigned char *mem, *mem2;
|
|
int count;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
|
|
/* Realize the cursor without interleaving */
|
|
if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
|
|
return NULL;
|
|
|
|
if (!(mem = xcalloc(1, size))) {
|
|
xfree(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 32 bit interleave */
|
|
DstS = (pointer)mem2;
|
|
DstM = DstS + (size >> 3);
|
|
pntr = (pointer)mem;
|
|
count = (size >> 2);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
count-=2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
xfree(mem2);
|
|
|
|
return mem;
|
|
}
|
|
|
|
static unsigned char*
|
|
RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
|
|
{
|
|
CARD32 *DstS, *DstM;
|
|
CARD32 *pntr;
|
|
unsigned char *mem, *mem2;
|
|
int count;
|
|
int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
|
|
|
|
/* Realize the cursor without interleaving */
|
|
if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
|
|
return NULL;
|
|
|
|
if (!(mem = xcalloc(1, size))) {
|
|
xfree(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 64 bit interleave */
|
|
DstS = (pointer)mem2;
|
|
DstM = DstS + (size >> 3);
|
|
pntr = (pointer)mem;
|
|
count = (size >> 2);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
*pntr++ = *DstM++;
|
|
count-=4;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
xfree(mem2);
|
|
|
|
return mem;
|
|
}
|