1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include <string.h>
7
8#include "misc.h"
9#include "xf86.h"
10#include "xf86_OSproc.h"
11
12#include <X11/X.h>
13#include "scrnintstr.h"
14#include "pixmapstr.h"
15#include "windowstr.h"
16#include "xf86str.h"
17#include "cursorstr.h"
18#include "mi.h"
19#include "mipointer.h"
20#include "xf86CursorPriv.h"
21
22#include "servermd.h"
23
24#if BITMAP_SCANLINE_PAD == 64
25
26#if 1
27/* Cursors might be only 32 wide. Give'em a chance */
28#define SCANLINE CARD32
29#define CUR_BITMAP_SCANLINE_PAD 32
30#define CUR_LOG2_BITMAP_PAD 5
31#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
32#else
33#define SCANLINE CARD64
34#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
35#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
36#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
37static CARD64 xf86CARD64ReverseBits(CARD64 w);
38
39static CARD64
40xf86CARD64ReverseBits(CARD64 w)
41{
42  unsigned char *p = (unsigned char *)&w;
43
44  p[0] = byte_reversed[p[0]];
45  p[1] = byte_reversed[p[1]];
46  p[2] = byte_reversed[p[2]];
47  p[3] = byte_reversed[p[3]];
48  p[4] = byte_reversed[p[4]];
49  p[5] = byte_reversed[p[5]];
50  p[6] = byte_reversed[p[6]];
51  p[7] = byte_reversed[p[7]];
52
53  return w;
54}
55#endif
56
57#else
58
59#define SCANLINE CARD32
60#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
61#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
62#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
63
64#endif /* BITMAP_SCANLINE_PAD == 64 */
65
66static unsigned char* RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
67static unsigned char* RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
68static unsigned char* RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
69static unsigned char* RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
70static unsigned char* RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
71static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
72
73Bool
74xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
75{
76    if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
77	return FALSE;
78
79    /* These are required for now */
80    if (!infoPtr->SetCursorPosition ||
81	!infoPtr->LoadCursorImage ||
82	!infoPtr->HideCursor ||
83	!infoPtr->ShowCursor ||
84	!infoPtr->SetCursorColors)
85	return FALSE;
86
87    if (infoPtr->RealizeCursor) {
88	/* Don't overwrite a driver provided Realize Cursor function */
89    } else
90    if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
91	infoPtr->RealizeCursor = RealizeCursorInterleave1;
92    } else
93    if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
94	infoPtr->RealizeCursor = RealizeCursorInterleave8;
95    } else
96    if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
97	infoPtr->RealizeCursor = RealizeCursorInterleave16;
98    } else
99    if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
100	infoPtr->RealizeCursor = RealizeCursorInterleave32;
101    } else
102    if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
103	infoPtr->RealizeCursor = RealizeCursorInterleave64;
104    } else {    /* not interleaved */
105	infoPtr->RealizeCursor = RealizeCursorInterleave0;
106    }
107
108    infoPtr->pScrn = xf86Screens[pScreen->myNum];
109
110    return TRUE;
111}
112
113void
114xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
115{
116    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
117	&pScreen->devPrivates, xf86CursorScreenKey);
118    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
119    unsigned char *bits;
120
121    if (pCurs == NullCursor) {
122	(*infoPtr->HideCursor)(infoPtr->pScrn);
123	return;
124    }
125
126    bits = dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen));
127
128    x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
129    y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
130
131#ifdef ARGB_CURSOR
132    if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB)
133#endif
134    if (!bits) {
135	bits = (*infoPtr->RealizeCursor)(infoPtr, pCurs);
136	dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), bits);
137    }
138
139    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
140	(*infoPtr->HideCursor)(infoPtr->pScrn);
141
142#ifdef ARGB_CURSOR
143    if (pCurs->bits->argb && infoPtr->LoadCursorARGB)
144	(*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs);
145    else
146#endif
147    if (bits)
148	(*infoPtr->LoadCursorImage)(infoPtr->pScrn, bits);
149
150    xf86RecolorCursor(pScreen, pCurs, 1);
151
152    (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y);
153
154    (*infoPtr->ShowCursor)(infoPtr->pScrn);
155}
156
157void
158xf86SetTransparentCursor(ScreenPtr pScreen)
159{
160    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
161	&pScreen->devPrivates, xf86CursorScreenKey);
162    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
163
164    if (!ScreenPriv->transparentData)
165	ScreenPriv->transparentData =
166	    (*infoPtr->RealizeCursor)(infoPtr, NullCursor);
167
168    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
169	(*infoPtr->HideCursor)(infoPtr->pScrn);
170
171    if (ScreenPriv->transparentData)
172	(*infoPtr->LoadCursorImage)(infoPtr->pScrn,
173				    ScreenPriv->transparentData);
174
175    (*infoPtr->ShowCursor)(infoPtr->pScrn);
176}
177
178void
179xf86MoveCursor(ScreenPtr pScreen, int x, int y)
180{
181    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
182	&pScreen->devPrivates, xf86CursorScreenKey);
183    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
184
185    x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX;
186    y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
187
188    (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y);
189}
190
191void
192xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
193{
194    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
195	&pScreen->devPrivates, xf86CursorScreenKey);
196    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
197
198#ifdef ARGB_CURSOR
199    /* recoloring isn't applicable to ARGB cursors and drivers
200       shouldn't have to ignore SetCursorColors requests */
201    if (pCurs->bits->argb)
202        return;
203#endif
204
205    if (ScreenPriv->PalettedCursor) {
206	xColorItem sourceColor, maskColor;
207	ColormapPtr pmap = ScreenPriv->pInstalledMap;
208
209	if (!pmap)
210	    return;
211
212	sourceColor.red = pCurs->foreRed;
213	sourceColor.green = pCurs->foreGreen;
214	sourceColor.blue = pCurs->foreBlue;
215	FakeAllocColor(pmap, &sourceColor);
216	maskColor.red = pCurs->backRed;
217	maskColor.green = pCurs->backGreen;
218	maskColor.blue = pCurs->backBlue;
219	FakeAllocColor(pmap, &maskColor);
220	FakeFreeColor(pmap, sourceColor.pixel);
221	FakeFreeColor(pmap, maskColor.pixel);
222	(*infoPtr->SetCursorColors)(infoPtr->pScrn,
223		maskColor.pixel, sourceColor.pixel);
224    } else {    /* Pass colors in 8-8-8 RGB format */
225	(*infoPtr->SetCursorColors)(infoPtr->pScrn,
226	    (pCurs->backBlue >> 8) |
227	    ((pCurs->backGreen >> 8) << 8) |
228	    ((pCurs->backRed >> 8) << 16),
229	    (pCurs->foreBlue >> 8) |
230	    ((pCurs->foreGreen >> 8) << 8) |
231	    ((pCurs->foreRed >> 8) << 16)
232	);
233    }
234}
235
236/* These functions assume that MaxWidth is a multiple of 32 */
237static unsigned char*
238RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
239{
240
241    SCANLINE *SrcS, *SrcM, *DstS, *DstM;
242    SCANLINE *pSrc, *pMsk;
243    unsigned char *mem;
244    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
245    int SrcPitch, DstPitch, Pitch, y, x;
246    /* how many words are in the source or mask */
247    int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
248
249
250    if (!(mem = calloc(1, size)))
251	return NULL;
252
253    if (pCurs == NullCursor) {
254	if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
255	    DstM = (SCANLINE*)mem;
256	    if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
257		DstM += words;
258	    memset(DstM, -1, words * sizeof(SCANLINE));
259	}
260	return mem;
261    }
262
263    /* SrcPitch == the number of scanlines wide the cursor image is */
264    SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
265      CUR_LOG2_BITMAP_PAD;
266
267    /* DstPitch is the width of the hw cursor in scanlines */
268    DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
269    Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
270
271    SrcS = (SCANLINE*)pCurs->bits->source;
272    SrcM = (SCANLINE*)pCurs->bits->mask;
273    DstS = (SCANLINE*)mem;
274    DstM = DstS + words;
275
276    if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
277	SCANLINE *tmp;
278	tmp = DstS; DstS = DstM; DstM = tmp;
279    }
280
281    if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
282	for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
283	    y--;
284	    pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
285	    for(x = 0; x < Pitch; x++) {
286		pSrc[x] = SrcS[x] & SrcM[x];
287		pMsk[x] = SrcM[x];
288	    }
289	}
290    } else {
291	for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
292	    y--;
293	    pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
294	    for(x = 0; x < Pitch; x++) {
295		pSrc[x] = SrcS[x];
296		pMsk[x] = SrcM[x];
297	    }
298	}
299    }
300
301    if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
302	int count = size;
303	unsigned char* pntr1 = (unsigned char *)DstS;
304	unsigned char* pntr2 = (unsigned char *)DstM;
305	unsigned char a, b;
306	while (count) {
307
308	   a = *pntr1;
309	   b = *pntr2;
310	   *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
311	   *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
312	   pntr1++; pntr2++;
313	   count-=2;
314	}
315    }
316
317    /*
318     * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
319     * out entire source mask.
320     */
321    if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
322	int count = words;
323	SCANLINE* pntr = DstM;
324	while (count--) {
325	   *pntr = ~(*pntr);
326	    pntr++;
327	}
328    }
329
330    if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
331	for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
332	    y--;
333	    pSrc+=DstPitch, pMsk+=DstPitch) {
334	    for(x = 0; x < Pitch; x++) {
335		pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
336		pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
337	    }
338	}
339    }
340
341    return mem;
342}
343
344static unsigned char*
345RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
346{
347    unsigned char *DstS, *DstM;
348    unsigned char *pntr;
349    unsigned char *mem, *mem2;
350    int count;
351    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
352
353    /* Realize the cursor without interleaving */
354    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
355	return NULL;
356
357    if (!(mem = calloc(1, size))) {
358	free(mem2);
359	return NULL;
360    }
361
362     /* 1 bit interleave */
363    DstS = mem2;
364    DstM = DstS + (size >> 1);
365    pntr = mem;
366    count = size;
367    while (count) {
368	*pntr++ = ((*DstS&0x01)     ) | ((*DstM&0x01) << 1) |
369		  ((*DstS&0x02) << 1) | ((*DstM&0x02) << 2) |
370		  ((*DstS&0x04) << 2) | ((*DstM&0x04) << 3) |
371		  ((*DstS&0x08) << 3) | ((*DstM&0x08) << 4);
372	*pntr++ = ((*DstS&0x10) >> 4) | ((*DstM&0x10) >> 3) |
373		  ((*DstS&0x20) >> 3) | ((*DstM&0x20) >> 2) |
374		  ((*DstS&0x40) >> 2) | ((*DstM&0x40) >> 1) |
375		  ((*DstS&0x80) >> 1) | ((*DstM&0x80)     );
376	DstS++;
377	DstM++;
378	count-=2;
379    }
380
381    /* Free the uninterleaved cursor */
382    free(mem2);
383
384    return mem;
385}
386
387static unsigned char*
388RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
389{
390    unsigned char *DstS, *DstM;
391    unsigned char *pntr;
392    unsigned char *mem, *mem2;
393    int count;
394    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
395
396    /* Realize the cursor without interleaving */
397    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
398	return NULL;
399
400    if (!(mem = calloc(1, size))) {
401	free(mem2);
402	return NULL;
403    }
404
405    /* 8 bit interleave */
406    DstS = mem2;
407    DstM = DstS + (size >> 1);
408    pntr = mem;
409    count = size;
410    while (count) {
411	*pntr++ = *DstS++;
412	*pntr++ = *DstM++;
413	count-=2;
414    }
415
416    /* Free the uninterleaved cursor */
417    free(mem2);
418
419    return mem;
420}
421
422static unsigned char*
423RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
424{
425    unsigned short *DstS, *DstM;
426    unsigned short *pntr;
427    unsigned char *mem, *mem2;
428    int count;
429    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
430
431    /* Realize the cursor without interleaving */
432    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
433	return NULL;
434
435    if (!(mem = calloc(1, size))) {
436	free(mem2);
437	return NULL;
438    }
439
440    /* 16 bit interleave */
441    DstS = (pointer)mem2;
442    DstM = DstS + (size >> 2);
443    pntr = (pointer)mem;
444    count = (size >> 1);
445    while (count) {
446	*pntr++ = *DstS++;
447	*pntr++ = *DstM++;
448	count-=2;
449    }
450
451    /* Free the uninterleaved cursor */
452    free(mem2);
453
454    return mem;
455}
456
457static unsigned char*
458RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
459{
460    CARD32 *DstS, *DstM;
461    CARD32 *pntr;
462    unsigned char *mem, *mem2;
463    int count;
464    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
465
466    /* Realize the cursor without interleaving */
467    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
468	return NULL;
469
470    if (!(mem = calloc(1, size))) {
471	free(mem2);
472	return NULL;
473    }
474
475    /* 32 bit interleave */
476    DstS = (pointer)mem2;
477    DstM = DstS + (size >> 3);
478    pntr = (pointer)mem;
479    count = (size >> 2);
480    while (count) {
481	*pntr++ = *DstS++;
482	*pntr++ = *DstM++;
483	count-=2;
484    }
485
486    /* Free the uninterleaved cursor */
487    free(mem2);
488
489    return mem;
490}
491
492static unsigned char*
493RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
494{
495    CARD32 *DstS, *DstM;
496    CARD32 *pntr;
497    unsigned char *mem, *mem2;
498    int count;
499    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
500
501    /* Realize the cursor without interleaving */
502    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
503	return NULL;
504
505    if (!(mem = calloc(1, size))) {
506	free(mem2);
507	return NULL;
508    }
509
510    /* 64 bit interleave */
511    DstS = (pointer)mem2;
512    DstM = DstS + (size >> 3);
513    pntr = (pointer)mem;
514    count = (size >> 2);
515    while (count) {
516	*pntr++ = *DstS++;
517	*pntr++ = *DstS++;
518	*pntr++ = *DstM++;
519	*pntr++ = *DstM++;
520	count-=4;
521    }
522
523    /* Free the uninterleaved cursor */
524    free(mem2);
525
526    return mem;
527}
528