Currently with PRIME if we detect a secondary GPU, we switch to using SW cursors, this isn't optimal, esp for the intel/nvidia combinations, we have no choice for the USB offload devices. This patch checks on each slave screen if hw cursors are enabled, and also calls set cursor and move cursor on all screens. Cc: Aaron Plattner <aplattner@nvidia.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Michel Dänzer <michel.daenzer@amd.com> Reviewed-by: Keith Packard <keithp@keithp.com>
633 lines
18 KiB
C
633 lines
18 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 "randrstr.h"
|
|
#include "xf86CursorPriv.h"
|
|
|
|
#include "servermd.h"
|
|
|
|
static CARD32
|
|
xf86ReverseBitOrder(CARD32 v)
|
|
{
|
|
return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) |
|
|
((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) |
|
|
((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) |
|
|
((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7));
|
|
}
|
|
|
|
#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 ||
|
|
!xf86DriverHasLoadCursorImage(infoPtr) ||
|
|
!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 = xf86ScreenToScrn(pScreen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
xf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
|
|
{
|
|
return
|
|
(cursor->bits->argb && infoPtr->UseHWCursorARGB &&
|
|
infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
|
|
(cursor->bits->argb == 0 &&
|
|
cursor->bits->height <= infoPtr->MaxHeight &&
|
|
cursor->bits->width <= infoPtr->MaxWidth &&
|
|
(!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
|
|
}
|
|
|
|
Bool
|
|
xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
|
|
{
|
|
ScreenPtr pSlave;
|
|
|
|
if (!xf86ScreenCheckHWCursor(pScreen, cursor, infoPtr))
|
|
return FALSE;
|
|
|
|
/* ask each driver consuming a pixmap if it can support HW cursor */
|
|
xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
|
|
xf86CursorScreenPtr sPriv;
|
|
|
|
if (!RRHasScanoutPixmap(pSlave))
|
|
continue;
|
|
|
|
sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
|
|
if (!xf86ScreenCheckHWCursor(pSlave, cursor, sPriv->CursorInfoPtr))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
xf86ScreenSetCursor(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 TRUE;
|
|
}
|
|
|
|
/*
|
|
* Hot plugged GPU's do not have a CursorScreenKey, force sw cursor.
|
|
* This check can be removed once dix/privates.c gets relocation code for
|
|
* PRIVATE_CURSOR. Also see the related comment in AddGPUScreen().
|
|
*/
|
|
if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
|
|
return FALSE;
|
|
|
|
bits =
|
|
dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
|
|
|
|
x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
|
|
y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
|
|
|
|
if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
|
|
if (!bits) {
|
|
bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
|
|
dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
|
|
bits);
|
|
}
|
|
|
|
if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
|
|
(*infoPtr->HideCursor) (infoPtr->pScrn);
|
|
|
|
if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
|
|
if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
|
|
return FALSE;
|
|
} else
|
|
if (bits)
|
|
if (!xf86DriverLoadCursorImage (infoPtr, bits))
|
|
return FALSE;
|
|
|
|
xf86RecolorCursor(pScreen, pCurs, 1);
|
|
|
|
(*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
|
|
|
|
(*infoPtr->ShowCursor) (infoPtr->pScrn);
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
|
|
{
|
|
ScreenPtr pSlave;
|
|
|
|
if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
|
|
return FALSE;
|
|
|
|
/* ask each slave driver to set the cursor. */
|
|
xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
|
|
if (!RRHasScanoutPixmap(pSlave))
|
|
continue;
|
|
|
|
if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
|
|
/*
|
|
* hide the master (and successfully set slave) cursors,
|
|
* otherwise both the hw and sw cursor will show.
|
|
*/
|
|
xf86SetCursor(pScreen, NullCursor, x, y);
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
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)
|
|
xf86DriverLoadCursorImage (infoPtr,
|
|
ScreenPriv->transparentData);
|
|
|
|
(*infoPtr->ShowCursor) (infoPtr->pScrn);
|
|
}
|
|
|
|
static void
|
|
xf86ScreenMoveCursor(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
|
|
xf86MoveCursor(ScreenPtr pScreen, int x, int y)
|
|
{
|
|
ScreenPtr pSlave;
|
|
|
|
xf86ScreenMoveCursor(pScreen, x, y);
|
|
|
|
/* ask each slave driver to move the cursor */
|
|
xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
|
|
if (!RRHasScanoutPixmap(pSlave))
|
|
continue;
|
|
|
|
xf86ScreenMoveCursor(pSlave, x, y);
|
|
}
|
|
}
|
|
|
|
void
|
|
xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
|
|
{
|
|
xf86CursorScreenPtr ScreenPriv =
|
|
(xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
|
|
xf86CursorScreenKey);
|
|
xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
|
|
|
|
/* recoloring isn't applicable to ARGB cursors and drivers
|
|
shouldn't have to ignore SetCursorColors requests */
|
|
if (pCurs->bits->argb)
|
|
return;
|
|
|
|
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 = calloc(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 = calloc(1, size))) {
|
|
free(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 */
|
|
free(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 = calloc(1, size))) {
|
|
free(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 */
|
|
free(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 = calloc(1, size))) {
|
|
free(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 16 bit interleave */
|
|
DstS = (void *) mem2;
|
|
DstM = DstS + (size >> 2);
|
|
pntr = (void *) mem;
|
|
count = (size >> 1);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
count -= 2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
free(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 = calloc(1, size))) {
|
|
free(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 32 bit interleave */
|
|
DstS = (void *) mem2;
|
|
DstM = DstS + (size >> 3);
|
|
pntr = (void *) mem;
|
|
count = (size >> 2);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
count -= 2;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
free(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 = calloc(1, size))) {
|
|
free(mem2);
|
|
return NULL;
|
|
}
|
|
|
|
/* 64 bit interleave */
|
|
DstS = (void *) mem2;
|
|
DstM = DstS + (size >> 3);
|
|
pntr = (void *) mem;
|
|
count = (size >> 2);
|
|
while (count) {
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstS++;
|
|
*pntr++ = *DstM++;
|
|
*pntr++ = *DstM++;
|
|
count -= 4;
|
|
}
|
|
|
|
/* Free the uninterleaved cursor */
|
|
free(mem2);
|
|
|
|
return mem;
|
|
}
|