1*4882a593Smuzhiyun
2*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
3*4882a593Smuzhiyun #include <xorg-config.h>
4*4882a593Smuzhiyun #endif
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <string.h>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include "misc.h"
9*4882a593Smuzhiyun #include "xf86.h"
10*4882a593Smuzhiyun #include "xf86_OSproc.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <X11/X.h>
13*4882a593Smuzhiyun #include "scrnintstr.h"
14*4882a593Smuzhiyun #include "pixmapstr.h"
15*4882a593Smuzhiyun #include "windowstr.h"
16*4882a593Smuzhiyun #include "xf86str.h"
17*4882a593Smuzhiyun #include "cursorstr.h"
18*4882a593Smuzhiyun #include "mi.h"
19*4882a593Smuzhiyun #include "mipointer.h"
20*4882a593Smuzhiyun #include "randrstr.h"
21*4882a593Smuzhiyun #include "xf86CursorPriv.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "servermd.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun static void
26*4882a593Smuzhiyun xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static CARD32
xf86ReverseBitOrder(CARD32 v)29*4882a593Smuzhiyun xf86ReverseBitOrder(CARD32 v)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) |
32*4882a593Smuzhiyun ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) |
33*4882a593Smuzhiyun ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) |
34*4882a593Smuzhiyun ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7));
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #if BITMAP_SCANLINE_PAD == 64
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #if 1
40*4882a593Smuzhiyun /* Cursors might be only 32 wide. Give'em a chance */
41*4882a593Smuzhiyun #define SCANLINE CARD32
42*4882a593Smuzhiyun #define CUR_BITMAP_SCANLINE_PAD 32
43*4882a593Smuzhiyun #define CUR_LOG2_BITMAP_PAD 5
44*4882a593Smuzhiyun #define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
45*4882a593Smuzhiyun #else
46*4882a593Smuzhiyun #define SCANLINE CARD64
47*4882a593Smuzhiyun #define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
48*4882a593Smuzhiyun #define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
49*4882a593Smuzhiyun #define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
50*4882a593Smuzhiyun static CARD64 xf86CARD64ReverseBits(CARD64 w);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static CARD64
xf86CARD64ReverseBits(CARD64 w)53*4882a593Smuzhiyun xf86CARD64ReverseBits(CARD64 w)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun unsigned char *p = (unsigned char *) &w;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun p[0] = byte_reversed[p[0]];
58*4882a593Smuzhiyun p[1] = byte_reversed[p[1]];
59*4882a593Smuzhiyun p[2] = byte_reversed[p[2]];
60*4882a593Smuzhiyun p[3] = byte_reversed[p[3]];
61*4882a593Smuzhiyun p[4] = byte_reversed[p[4]];
62*4882a593Smuzhiyun p[5] = byte_reversed[p[5]];
63*4882a593Smuzhiyun p[6] = byte_reversed[p[6]];
64*4882a593Smuzhiyun p[7] = byte_reversed[p[7]];
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun return w;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun #endif
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun #else
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun #define SCANLINE CARD32
73*4882a593Smuzhiyun #define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
74*4882a593Smuzhiyun #define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
75*4882a593Smuzhiyun #define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #endif /* BITMAP_SCANLINE_PAD == 64 */
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
80*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
81*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
82*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
83*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
84*4882a593Smuzhiyun static unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun Bool
xf86InitHardwareCursor(ScreenPtr pScreen,xf86CursorInfoPtr infoPtr)87*4882a593Smuzhiyun xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
90*4882a593Smuzhiyun return FALSE;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* These are required for now */
93*4882a593Smuzhiyun if (!infoPtr->SetCursorPosition ||
94*4882a593Smuzhiyun !xf86DriverHasLoadCursorImage(infoPtr) ||
95*4882a593Smuzhiyun !infoPtr->HideCursor ||
96*4882a593Smuzhiyun !xf86DriverHasShowCursor(infoPtr) ||
97*4882a593Smuzhiyun !infoPtr->SetCursorColors)
98*4882a593Smuzhiyun return FALSE;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun if (infoPtr->RealizeCursor) {
101*4882a593Smuzhiyun /* Don't overwrite a driver provided Realize Cursor function */
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
104*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave1;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
107*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave8;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
110*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave16;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
113*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave32;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
116*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave64;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun else { /* not interleaved */
119*4882a593Smuzhiyun infoPtr->RealizeCursor = RealizeCursorInterleave0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun infoPtr->pScrn = xf86ScreenToScrn(pScreen);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return TRUE;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun static Bool
xf86ScreenCheckHWCursor(ScreenPtr pScreen,CursorPtr cursor,xf86CursorInfoPtr infoPtr)128*4882a593Smuzhiyun xf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun return
131*4882a593Smuzhiyun (cursor->bits->argb && infoPtr->UseHWCursorARGB &&
132*4882a593Smuzhiyun infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
133*4882a593Smuzhiyun (cursor->bits->argb == 0 &&
134*4882a593Smuzhiyun cursor->bits->height <= infoPtr->MaxHeight &&
135*4882a593Smuzhiyun cursor->bits->width <= infoPtr->MaxWidth &&
136*4882a593Smuzhiyun (!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun Bool
xf86CheckHWCursor(ScreenPtr pScreen,CursorPtr cursor,xf86CursorInfoPtr infoPtr)140*4882a593Smuzhiyun xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun ScreenPtr pSlave;
143*4882a593Smuzhiyun Bool use_hw_cursor = TRUE;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun input_lock();
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (!xf86ScreenCheckHWCursor(pScreen, cursor, infoPtr)) {
148*4882a593Smuzhiyun use_hw_cursor = FALSE;
149*4882a593Smuzhiyun goto unlock;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* ask each driver consuming a pixmap if it can support HW cursor */
153*4882a593Smuzhiyun xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
154*4882a593Smuzhiyun xf86CursorScreenPtr sPriv;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (!RRHasScanoutPixmap(pSlave))
157*4882a593Smuzhiyun continue;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
160*4882a593Smuzhiyun if (!sPriv) { /* NULL if Option "SWCursor", possibly other conditions */
161*4882a593Smuzhiyun use_hw_cursor = FALSE;
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* FALSE if HWCursor not supported by slave */
166*4882a593Smuzhiyun if (!xf86ScreenCheckHWCursor(pSlave, cursor, sPriv->CursorInfoPtr)) {
167*4882a593Smuzhiyun use_hw_cursor = FALSE;
168*4882a593Smuzhiyun break;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun unlock:
173*4882a593Smuzhiyun input_unlock();
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun return use_hw_cursor;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun static Bool
xf86ScreenSetCursor(ScreenPtr pScreen,CursorPtr pCurs,int x,int y)179*4882a593Smuzhiyun xf86ScreenSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
182*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
183*4882a593Smuzhiyun xf86CursorScreenKey);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun xf86CursorInfoPtr infoPtr;
186*4882a593Smuzhiyun unsigned char *bits;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (!ScreenPriv) { /* NULL if Option "SWCursor" */
189*4882a593Smuzhiyun return (pCurs == NullCursor);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun infoPtr = ScreenPriv->CursorInfoPtr;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (pCurs == NullCursor) {
195*4882a593Smuzhiyun (*infoPtr->HideCursor) (infoPtr->pScrn);
196*4882a593Smuzhiyun return TRUE;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun * Hot plugged GPU's do not have a CursorScreenKey, force sw cursor.
201*4882a593Smuzhiyun * This check can be removed once dix/privates.c gets relocation code for
202*4882a593Smuzhiyun * PRIVATE_CURSOR. Also see the related comment in AddGPUScreen().
203*4882a593Smuzhiyun */
204*4882a593Smuzhiyun if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
205*4882a593Smuzhiyun return FALSE;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun bits =
208*4882a593Smuzhiyun dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun x -= infoPtr->pScrn->frameX0;
211*4882a593Smuzhiyun y -= infoPtr->pScrn->frameY0;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
214*4882a593Smuzhiyun if (!bits) {
215*4882a593Smuzhiyun bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
216*4882a593Smuzhiyun dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
217*4882a593Smuzhiyun bits);
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
221*4882a593Smuzhiyun (*infoPtr->HideCursor) (infoPtr->pScrn);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
224*4882a593Smuzhiyun if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
225*4882a593Smuzhiyun return FALSE;
226*4882a593Smuzhiyun } else
227*4882a593Smuzhiyun if (bits)
228*4882a593Smuzhiyun if (!xf86DriverLoadCursorImage (infoPtr, bits))
229*4882a593Smuzhiyun return FALSE;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun xf86RecolorCursor_locked (ScreenPriv, pCurs);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun return xf86DriverShowCursor(infoPtr);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun Bool
xf86SetCursor(ScreenPtr pScreen,CursorPtr pCurs,int x,int y)239*4882a593Smuzhiyun xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
242*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
243*4882a593Smuzhiyun xf86CursorScreenKey);
244*4882a593Smuzhiyun ScreenPtr pSlave;
245*4882a593Smuzhiyun Bool ret = FALSE;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun input_lock();
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun x -= ScreenPriv->HotX;
250*4882a593Smuzhiyun y -= ScreenPriv->HotY;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
253*4882a593Smuzhiyun goto out;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* ask each slave driver to set the cursor. */
256*4882a593Smuzhiyun xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
257*4882a593Smuzhiyun if (!RRHasScanoutPixmap(pSlave))
258*4882a593Smuzhiyun continue;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
261*4882a593Smuzhiyun /*
262*4882a593Smuzhiyun * hide the master (and successfully set slave) cursors,
263*4882a593Smuzhiyun * otherwise both the hw and sw cursor will show.
264*4882a593Smuzhiyun */
265*4882a593Smuzhiyun xf86SetCursor(pScreen, NullCursor, x, y);
266*4882a593Smuzhiyun goto out;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun ret = TRUE;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun out:
272*4882a593Smuzhiyun input_unlock();
273*4882a593Smuzhiyun return ret;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun void
xf86SetTransparentCursor(ScreenPtr pScreen)277*4882a593Smuzhiyun xf86SetTransparentCursor(ScreenPtr pScreen)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
280*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
281*4882a593Smuzhiyun xf86CursorScreenKey);
282*4882a593Smuzhiyun xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun input_lock();
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (!ScreenPriv->transparentData)
287*4882a593Smuzhiyun ScreenPriv->transparentData =
288*4882a593Smuzhiyun (*infoPtr->RealizeCursor) (infoPtr, NullCursor);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
291*4882a593Smuzhiyun (*infoPtr->HideCursor) (infoPtr->pScrn);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (ScreenPriv->transparentData)
294*4882a593Smuzhiyun xf86DriverLoadCursorImage (infoPtr,
295*4882a593Smuzhiyun ScreenPriv->transparentData);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun xf86DriverShowCursor(infoPtr);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun input_unlock();
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun static void
xf86ScreenMoveCursor(ScreenPtr pScreen,int x,int y)303*4882a593Smuzhiyun xf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
306*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
307*4882a593Smuzhiyun xf86CursorScreenKey);
308*4882a593Smuzhiyun xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun x -= infoPtr->pScrn->frameX0;
311*4882a593Smuzhiyun y -= infoPtr->pScrn->frameY0;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun void
xf86MoveCursor(ScreenPtr pScreen,int x,int y)317*4882a593Smuzhiyun xf86MoveCursor(ScreenPtr pScreen, int x, int y)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
320*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
321*4882a593Smuzhiyun xf86CursorScreenKey);
322*4882a593Smuzhiyun ScreenPtr pSlave;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun input_lock();
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun x -= ScreenPriv->HotX;
327*4882a593Smuzhiyun y -= ScreenPriv->HotY;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun xf86ScreenMoveCursor(pScreen, x, y);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* ask each slave driver to move the cursor */
332*4882a593Smuzhiyun xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
333*4882a593Smuzhiyun if (!RRHasScanoutPixmap(pSlave))
334*4882a593Smuzhiyun continue;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun xf86ScreenMoveCursor(pSlave, x, y);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun input_unlock();
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun static void
xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv,CursorPtr pCurs)343*4882a593Smuzhiyun xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /* recoloring isn't applicable to ARGB cursors and drivers
348*4882a593Smuzhiyun shouldn't have to ignore SetCursorColors requests */
349*4882a593Smuzhiyun if (pCurs->bits->argb)
350*4882a593Smuzhiyun return;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun if (ScreenPriv->PalettedCursor) {
353*4882a593Smuzhiyun xColorItem sourceColor, maskColor;
354*4882a593Smuzhiyun ColormapPtr pmap = ScreenPriv->pInstalledMap;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (!pmap)
357*4882a593Smuzhiyun return;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun sourceColor.red = pCurs->foreRed;
360*4882a593Smuzhiyun sourceColor.green = pCurs->foreGreen;
361*4882a593Smuzhiyun sourceColor.blue = pCurs->foreBlue;
362*4882a593Smuzhiyun FakeAllocColor(pmap, &sourceColor);
363*4882a593Smuzhiyun maskColor.red = pCurs->backRed;
364*4882a593Smuzhiyun maskColor.green = pCurs->backGreen;
365*4882a593Smuzhiyun maskColor.blue = pCurs->backBlue;
366*4882a593Smuzhiyun FakeAllocColor(pmap, &maskColor);
367*4882a593Smuzhiyun FakeFreeColor(pmap, sourceColor.pixel);
368*4882a593Smuzhiyun FakeFreeColor(pmap, maskColor.pixel);
369*4882a593Smuzhiyun (*infoPtr->SetCursorColors) (infoPtr->pScrn,
370*4882a593Smuzhiyun maskColor.pixel, sourceColor.pixel);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun else { /* Pass colors in 8-8-8 RGB format */
373*4882a593Smuzhiyun (*infoPtr->SetCursorColors) (infoPtr->pScrn,
374*4882a593Smuzhiyun (pCurs->backBlue >> 8) |
375*4882a593Smuzhiyun ((pCurs->backGreen >> 8) << 8) |
376*4882a593Smuzhiyun ((pCurs->backRed >> 8) << 16),
377*4882a593Smuzhiyun (pCurs->foreBlue >> 8) |
378*4882a593Smuzhiyun ((pCurs->foreGreen >> 8) << 8) |
379*4882a593Smuzhiyun ((pCurs->foreRed >> 8) << 16)
380*4882a593Smuzhiyun );
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun void
xf86RecolorCursor(ScreenPtr pScreen,CursorPtr pCurs,Bool displayed)385*4882a593Smuzhiyun xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
388*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
389*4882a593Smuzhiyun xf86CursorScreenKey);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun input_lock();
392*4882a593Smuzhiyun xf86RecolorCursor_locked (ScreenPriv, pCurs);
393*4882a593Smuzhiyun input_unlock();
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* These functions assume that MaxWidth is a multiple of 32 */
397*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)398*4882a593Smuzhiyun RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun SCANLINE *SrcS, *SrcM, *DstS, *DstM;
402*4882a593Smuzhiyun SCANLINE *pSrc, *pMsk;
403*4882a593Smuzhiyun unsigned char *mem;
404*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
405*4882a593Smuzhiyun int SrcPitch, DstPitch, Pitch, y, x;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* how many words are in the source or mask */
408*4882a593Smuzhiyun int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (!(mem = calloc(1, size)))
411*4882a593Smuzhiyun return NULL;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if (pCurs == NullCursor) {
414*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
415*4882a593Smuzhiyun DstM = (SCANLINE *) mem;
416*4882a593Smuzhiyun if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
417*4882a593Smuzhiyun DstM += words;
418*4882a593Smuzhiyun memset(DstM, -1, words * sizeof(SCANLINE));
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun return mem;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /* SrcPitch == the number of scanlines wide the cursor image is */
424*4882a593Smuzhiyun SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
425*4882a593Smuzhiyun CUR_LOG2_BITMAP_PAD;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /* DstPitch is the width of the hw cursor in scanlines */
428*4882a593Smuzhiyun DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
429*4882a593Smuzhiyun Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun SrcS = (SCANLINE *) pCurs->bits->source;
432*4882a593Smuzhiyun SrcM = (SCANLINE *) pCurs->bits->mask;
433*4882a593Smuzhiyun DstS = (SCANLINE *) mem;
434*4882a593Smuzhiyun DstM = DstS + words;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
437*4882a593Smuzhiyun SCANLINE *tmp;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun tmp = DstS;
440*4882a593Smuzhiyun DstS = DstM;
441*4882a593Smuzhiyun DstM = tmp;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
445*4882a593Smuzhiyun for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
446*4882a593Smuzhiyun y--;
447*4882a593Smuzhiyun pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
448*4882a593Smuzhiyun SrcPitch) {
449*4882a593Smuzhiyun for (x = 0; x < Pitch; x++) {
450*4882a593Smuzhiyun pSrc[x] = SrcS[x] & SrcM[x];
451*4882a593Smuzhiyun pMsk[x] = SrcM[x];
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun else {
456*4882a593Smuzhiyun for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
457*4882a593Smuzhiyun y--;
458*4882a593Smuzhiyun pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
459*4882a593Smuzhiyun SrcPitch) {
460*4882a593Smuzhiyun for (x = 0; x < Pitch; x++) {
461*4882a593Smuzhiyun pSrc[x] = SrcS[x];
462*4882a593Smuzhiyun pMsk[x] = SrcM[x];
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
468*4882a593Smuzhiyun int count = size;
469*4882a593Smuzhiyun unsigned char *pntr1 = (unsigned char *) DstS;
470*4882a593Smuzhiyun unsigned char *pntr2 = (unsigned char *) DstM;
471*4882a593Smuzhiyun unsigned char a, b;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun while (count) {
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun a = *pntr1;
476*4882a593Smuzhiyun b = *pntr2;
477*4882a593Smuzhiyun *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
478*4882a593Smuzhiyun *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
479*4882a593Smuzhiyun pntr1++;
480*4882a593Smuzhiyun pntr2++;
481*4882a593Smuzhiyun count -= 2;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun /*
486*4882a593Smuzhiyun * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
487*4882a593Smuzhiyun * out entire source mask.
488*4882a593Smuzhiyun */
489*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
490*4882a593Smuzhiyun int count = words;
491*4882a593Smuzhiyun SCANLINE *pntr = DstM;
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun while (count--) {
494*4882a593Smuzhiyun *pntr = ~(*pntr);
495*4882a593Smuzhiyun pntr++;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
500*4882a593Smuzhiyun for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
501*4882a593Smuzhiyun y--; pSrc += DstPitch, pMsk += DstPitch) {
502*4882a593Smuzhiyun for (x = 0; x < Pitch; x++) {
503*4882a593Smuzhiyun pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
504*4882a593Smuzhiyun pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun return mem;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)513*4882a593Smuzhiyun RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun unsigned char *DstS, *DstM;
516*4882a593Smuzhiyun unsigned char *pntr;
517*4882a593Smuzhiyun unsigned char *mem, *mem2;
518*4882a593Smuzhiyun int count;
519*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* Realize the cursor without interleaving */
522*4882a593Smuzhiyun if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
523*4882a593Smuzhiyun return NULL;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (!(mem = calloc(1, size))) {
526*4882a593Smuzhiyun free(mem2);
527*4882a593Smuzhiyun return NULL;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun /* 1 bit interleave */
531*4882a593Smuzhiyun DstS = mem2;
532*4882a593Smuzhiyun DstM = DstS + (size >> 1);
533*4882a593Smuzhiyun pntr = mem;
534*4882a593Smuzhiyun count = size;
535*4882a593Smuzhiyun while (count) {
536*4882a593Smuzhiyun *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) |
537*4882a593Smuzhiyun ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) |
538*4882a593Smuzhiyun ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) |
539*4882a593Smuzhiyun ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4);
540*4882a593Smuzhiyun *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) |
541*4882a593Smuzhiyun ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) |
542*4882a593Smuzhiyun ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) |
543*4882a593Smuzhiyun ((*DstS & 0x80) >> 1) | ((*DstM & 0x80));
544*4882a593Smuzhiyun DstS++;
545*4882a593Smuzhiyun DstM++;
546*4882a593Smuzhiyun count -= 2;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* Free the uninterleaved cursor */
550*4882a593Smuzhiyun free(mem2);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun return mem;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)556*4882a593Smuzhiyun RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun unsigned char *DstS, *DstM;
559*4882a593Smuzhiyun unsigned char *pntr;
560*4882a593Smuzhiyun unsigned char *mem, *mem2;
561*4882a593Smuzhiyun int count;
562*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* Realize the cursor without interleaving */
565*4882a593Smuzhiyun if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
566*4882a593Smuzhiyun return NULL;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun if (!(mem = calloc(1, size))) {
569*4882a593Smuzhiyun free(mem2);
570*4882a593Smuzhiyun return NULL;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* 8 bit interleave */
574*4882a593Smuzhiyun DstS = mem2;
575*4882a593Smuzhiyun DstM = DstS + (size >> 1);
576*4882a593Smuzhiyun pntr = mem;
577*4882a593Smuzhiyun count = size;
578*4882a593Smuzhiyun while (count) {
579*4882a593Smuzhiyun *pntr++ = *DstS++;
580*4882a593Smuzhiyun *pntr++ = *DstM++;
581*4882a593Smuzhiyun count -= 2;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /* Free the uninterleaved cursor */
585*4882a593Smuzhiyun free(mem2);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun return mem;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)591*4882a593Smuzhiyun RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun unsigned short *DstS, *DstM;
594*4882a593Smuzhiyun unsigned short *pntr;
595*4882a593Smuzhiyun unsigned char *mem, *mem2;
596*4882a593Smuzhiyun int count;
597*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun /* Realize the cursor without interleaving */
600*4882a593Smuzhiyun if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
601*4882a593Smuzhiyun return NULL;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (!(mem = calloc(1, size))) {
604*4882a593Smuzhiyun free(mem2);
605*4882a593Smuzhiyun return NULL;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /* 16 bit interleave */
609*4882a593Smuzhiyun DstS = (void *) mem2;
610*4882a593Smuzhiyun DstM = DstS + (size >> 2);
611*4882a593Smuzhiyun pntr = (void *) mem;
612*4882a593Smuzhiyun count = (size >> 1);
613*4882a593Smuzhiyun while (count) {
614*4882a593Smuzhiyun *pntr++ = *DstS++;
615*4882a593Smuzhiyun *pntr++ = *DstM++;
616*4882a593Smuzhiyun count -= 2;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun /* Free the uninterleaved cursor */
620*4882a593Smuzhiyun free(mem2);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun return mem;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)626*4882a593Smuzhiyun RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun CARD32 *DstS, *DstM;
629*4882a593Smuzhiyun CARD32 *pntr;
630*4882a593Smuzhiyun unsigned char *mem, *mem2;
631*4882a593Smuzhiyun int count;
632*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* Realize the cursor without interleaving */
635*4882a593Smuzhiyun if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
636*4882a593Smuzhiyun return NULL;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun if (!(mem = calloc(1, size))) {
639*4882a593Smuzhiyun free(mem2);
640*4882a593Smuzhiyun return NULL;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /* 32 bit interleave */
644*4882a593Smuzhiyun DstS = (void *) mem2;
645*4882a593Smuzhiyun DstM = DstS + (size >> 3);
646*4882a593Smuzhiyun pntr = (void *) mem;
647*4882a593Smuzhiyun count = (size >> 2);
648*4882a593Smuzhiyun while (count) {
649*4882a593Smuzhiyun *pntr++ = *DstS++;
650*4882a593Smuzhiyun *pntr++ = *DstM++;
651*4882a593Smuzhiyun count -= 2;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* Free the uninterleaved cursor */
655*4882a593Smuzhiyun free(mem2);
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun return mem;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun static unsigned char *
RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)661*4882a593Smuzhiyun RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun CARD32 *DstS, *DstM;
664*4882a593Smuzhiyun CARD32 *pntr;
665*4882a593Smuzhiyun unsigned char *mem, *mem2;
666*4882a593Smuzhiyun int count;
667*4882a593Smuzhiyun int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* Realize the cursor without interleaving */
670*4882a593Smuzhiyun if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
671*4882a593Smuzhiyun return NULL;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (!(mem = calloc(1, size))) {
674*4882a593Smuzhiyun free(mem2);
675*4882a593Smuzhiyun return NULL;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun /* 64 bit interleave */
679*4882a593Smuzhiyun DstS = (void *) mem2;
680*4882a593Smuzhiyun DstM = DstS + (size >> 3);
681*4882a593Smuzhiyun pntr = (void *) mem;
682*4882a593Smuzhiyun count = (size >> 2);
683*4882a593Smuzhiyun while (count) {
684*4882a593Smuzhiyun *pntr++ = *DstS++;
685*4882a593Smuzhiyun *pntr++ = *DstS++;
686*4882a593Smuzhiyun *pntr++ = *DstM++;
687*4882a593Smuzhiyun *pntr++ = *DstM++;
688*4882a593Smuzhiyun count -= 4;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun /* Free the uninterleaved cursor */
692*4882a593Smuzhiyun free(mem2);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun return mem;
695*4882a593Smuzhiyun }
696