xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/ramdac/xf86CursorRD.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 
2 #ifdef HAVE_XORG_CONFIG_H
3 #include <xorg-config.h>
4 #endif
5 
6 #include "xf86.h"
7 #include "xf86CursorPriv.h"
8 #include "colormapst.h"
9 #include "cursorstr.h"
10 
11 /* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for
12  * MPX.
13  * inputInfo is needed to pass the core pointer as the default argument into
14  * the cursor functions.
15  *
16  * Externing inputInfo is not the nice way to do it but it works.
17  */
18 #include "inputstr.h"
19 
20 DevPrivateKeyRec xf86CursorScreenKeyRec;
21 
22 /* sprite functions */
23 
24 static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
25 static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
26 static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
27 static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
28 static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr);
29 static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr);
30 
31 static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
32     xf86CursorRealizeCursor,
33     xf86CursorUnrealizeCursor,
34     xf86CursorSetCursor,
35     xf86CursorMoveCursor,
36     xf86DeviceCursorInitialize,
37     xf86DeviceCursorCleanup
38 };
39 
40 /* Screen functions */
41 
42 static void xf86CursorInstallColormap(ColormapPtr);
43 static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr,
44                                     Bool);
45 static Bool xf86CursorCloseScreen(ScreenPtr);
46 static void xf86CursorQueryBestSize(int, unsigned short *, unsigned short *,
47                                     ScreenPtr);
48 
49 /* ScrnInfoRec functions */
50 
51 static void xf86CursorEnableDisableFBAccess(ScrnInfoPtr, Bool);
52 static Bool xf86CursorSwitchMode(ScrnInfoPtr, DisplayModePtr);
53 
54 Bool
xf86InitCursor(ScreenPtr pScreen,xf86CursorInfoPtr infoPtr)55 xf86InitCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
56 {
57     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
58     xf86CursorScreenPtr ScreenPriv;
59     miPointerScreenPtr PointPriv;
60 
61     if (!xf86InitHardwareCursor(pScreen, infoPtr))
62         return FALSE;
63 
64     if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0))
65         return FALSE;
66 
67     ScreenPriv = calloc(1, sizeof(xf86CursorScreenRec));
68     if (!ScreenPriv)
69         return FALSE;
70 
71     dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv);
72 
73     ScreenPriv->SWCursor = TRUE;
74     ScreenPriv->isUp = FALSE;
75     ScreenPriv->CurrentCursor = NULL;
76     ScreenPriv->CursorInfoPtr = infoPtr;
77     ScreenPriv->PalettedCursor = FALSE;
78     ScreenPriv->pInstalledMap = NULL;
79 
80     ScreenPriv->CloseScreen = pScreen->CloseScreen;
81     pScreen->CloseScreen = xf86CursorCloseScreen;
82     ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
83     pScreen->QueryBestSize = xf86CursorQueryBestSize;
84     ScreenPriv->RecolorCursor = pScreen->RecolorCursor;
85     pScreen->RecolorCursor = xf86CursorRecolorCursor;
86 
87     if ((infoPtr->pScrn->bitsPerPixel == 8) &&
88         !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) {
89         ScreenPriv->InstallColormap = pScreen->InstallColormap;
90         pScreen->InstallColormap = xf86CursorInstallColormap;
91         ScreenPriv->PalettedCursor = TRUE;
92     }
93 
94     PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
95 
96     ScreenPriv->showTransparent = PointPriv->showTransparent;
97     if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT)
98         PointPriv->showTransparent = TRUE;
99     else
100         PointPriv->showTransparent = FALSE;
101     ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
102     PointPriv->spriteFuncs = &xf86CursorSpriteFuncs;
103 
104     ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
105     ScreenPriv->SwitchMode = pScrn->SwitchMode;
106 
107     ScreenPriv->ForceHWCursorCount = 0;
108     ScreenPriv->HWCursorForced = FALSE;
109 
110     pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess;
111     if (pScrn->SwitchMode)
112         pScrn->SwitchMode = xf86CursorSwitchMode;
113 
114     return TRUE;
115 }
116 
117 /***** Screen functions *****/
118 
119 static Bool
xf86CursorCloseScreen(ScreenPtr pScreen)120 xf86CursorCloseScreen(ScreenPtr pScreen)
121 {
122     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
123     miPointerScreenPtr PointPriv =
124         (miPointerScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
125                                               miPointerScreenKey);
126     xf86CursorScreenPtr ScreenPriv =
127         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
128                                                xf86CursorScreenKey);
129 
130     if (ScreenPriv->isUp && pScrn->vtSema)
131         xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
132 
133     if (ScreenPriv->CurrentCursor)
134         FreeCursor(ScreenPriv->CurrentCursor, None);
135 
136     pScreen->CloseScreen = ScreenPriv->CloseScreen;
137     pScreen->QueryBestSize = ScreenPriv->QueryBestSize;
138     pScreen->RecolorCursor = ScreenPriv->RecolorCursor;
139     if (ScreenPriv->InstallColormap)
140         pScreen->InstallColormap = ScreenPriv->InstallColormap;
141 
142     PointPriv->spriteFuncs = ScreenPriv->spriteFuncs;
143     PointPriv->showTransparent = ScreenPriv->showTransparent;
144 
145     pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess;
146     pScrn->SwitchMode = ScreenPriv->SwitchMode;
147 
148     free(ScreenPriv->transparentData);
149     free(ScreenPriv);
150 
151     return (*pScreen->CloseScreen) (pScreen);
152 }
153 
154 static void
xf86CursorQueryBestSize(int class,unsigned short * width,unsigned short * height,ScreenPtr pScreen)155 xf86CursorQueryBestSize(int class,
156                         unsigned short *width,
157                         unsigned short *height, ScreenPtr pScreen)
158 {
159     xf86CursorScreenPtr ScreenPriv =
160         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
161                                                xf86CursorScreenKey);
162 
163     if (class == CursorShape) {
164         if (*width > ScreenPriv->CursorInfoPtr->MaxWidth)
165             *width = ScreenPriv->CursorInfoPtr->MaxWidth;
166         if (*height > ScreenPriv->CursorInfoPtr->MaxHeight)
167             *height = ScreenPriv->CursorInfoPtr->MaxHeight;
168     }
169     else
170         (*ScreenPriv->QueryBestSize) (class, width, height, pScreen);
171 }
172 
173 static void
xf86CursorInstallColormap(ColormapPtr pMap)174 xf86CursorInstallColormap(ColormapPtr pMap)
175 {
176     xf86CursorScreenPtr ScreenPriv =
177         (xf86CursorScreenPtr) dixLookupPrivate(&pMap->pScreen->devPrivates,
178                                                xf86CursorScreenKey);
179 
180     ScreenPriv->pInstalledMap = pMap;
181 
182     (*ScreenPriv->InstallColormap) (pMap);
183 }
184 
185 static void
xf86CursorRecolorCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCurs,Bool displayed)186 xf86CursorRecolorCursor(DeviceIntPtr pDev,
187                         ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
188 {
189     xf86CursorScreenPtr ScreenPriv =
190         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
191                                                xf86CursorScreenKey);
192 
193     if (!displayed)
194         return;
195 
196     if (ScreenPriv->SWCursor)
197         (*ScreenPriv->RecolorCursor) (pDev, pScreen, pCurs, displayed);
198     else
199         xf86RecolorCursor(pScreen, pCurs, displayed);
200 }
201 
202 /***** ScrnInfoRec functions *********/
203 
204 static void
xf86CursorEnableDisableFBAccess(ScrnInfoPtr pScrn,Bool enable)205 xf86CursorEnableDisableFBAccess(ScrnInfoPtr pScrn, Bool enable)
206 {
207     DeviceIntPtr pDev = inputInfo.pointer;
208 
209     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
210     xf86CursorScreenPtr ScreenPriv =
211         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
212                                                xf86CursorScreenKey);
213 
214     if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
215         CursorPtr currentCursor = RefCursor(ScreenPriv->CurrentCursor);
216 
217         xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x,
218                             ScreenPriv->y);
219         ScreenPriv->isUp = FALSE;
220         ScreenPriv->SWCursor = TRUE;
221         ScreenPriv->SavedCursor = currentCursor;
222     }
223 
224     if (ScreenPriv->EnableDisableFBAccess)
225         (*ScreenPriv->EnableDisableFBAccess) (pScrn, enable);
226 
227     if (enable && ScreenPriv->SavedCursor) {
228         /*
229          * Re-set current cursor so drivers can react to FB access having been
230          * temporarily disabled.
231          */
232         xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor,
233                             ScreenPriv->x, ScreenPriv->y);
234         UnrefCursor(ScreenPriv->SavedCursor);
235         ScreenPriv->SavedCursor = NULL;
236     }
237 }
238 
239 static Bool
xf86CursorSwitchMode(ScrnInfoPtr pScrn,DisplayModePtr mode)240 xf86CursorSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
241 {
242     Bool ret;
243     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
244     xf86CursorScreenPtr ScreenPriv =
245         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
246                                                xf86CursorScreenKey);
247 
248     if (ScreenPriv->isUp) {
249         xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
250         ScreenPriv->isUp = FALSE;
251     }
252 
253     ret = (*ScreenPriv->SwitchMode) (pScrn, mode);
254 
255     /*
256      * Cannot restore cursor here because the new frame[XY][01] haven't been
257      * calculated yet.  However, because the hardware cursor was removed above,
258      * ensure the cursor is repainted by miPointerWarpCursor().
259      */
260     ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor;
261     miPointerSetWaitForUpdate(pScreen, FALSE);  /* Force cursor repaint */
262 
263     return ret;
264 }
265 
266 /****** miPointerSpriteFunctions *******/
267 
268 static Bool
xf86CursorRealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCurs)269 xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
270 {
271     xf86CursorScreenPtr ScreenPriv =
272         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
273                                                xf86CursorScreenKey);
274 
275     if (CursorRefCount(pCurs) <= 1)
276         dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
277                             NULL);
278 
279     return (*ScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCurs);
280 }
281 
282 static Bool
xf86CursorUnrealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCurs)283 xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
284 {
285     xf86CursorScreenPtr ScreenPriv =
286         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
287                                                xf86CursorScreenKey);
288 
289     if (CursorRefCount(pCurs) <= 1) {
290         free(dixLookupScreenPrivate
291              (&pCurs->devPrivates, CursorScreenKey, pScreen));
292         dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
293                             NULL);
294     }
295 
296     return (*ScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCurs);
297 }
298 
299 static void
xf86CursorSetCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCurs,int x,int y)300 xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
301                     int x, int y)
302 {
303     xf86CursorScreenPtr ScreenPriv =
304         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
305                                                xf86CursorScreenKey);
306     xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
307 
308     if (pCurs == NullCursor) {  /* means we're supposed to remove the cursor */
309         if (ScreenPriv->SWCursor ||
310             !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer))
311             (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, NullCursor, x,
312                                                    y);
313         else if (ScreenPriv->isUp) {
314             xf86SetCursor(pScreen, NullCursor, x, y);
315             ScreenPriv->isUp = FALSE;
316         }
317         if (ScreenPriv->CurrentCursor)
318             FreeCursor(ScreenPriv->CurrentCursor, None);
319         ScreenPriv->CurrentCursor = NullCursor;
320         return;
321     }
322 
323     /* only update for VCP, otherwise we get cursor jumps when removing a
324        sprite. The second cursor is never HW rendered anyway. */
325     if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) {
326         CursorPtr cursor = RefCursor(pCurs);
327         if (ScreenPriv->CurrentCursor)
328             FreeCursor(ScreenPriv->CurrentCursor, None);
329         ScreenPriv->CurrentCursor = cursor;
330         ScreenPriv->x = x;
331         ScreenPriv->y = y;
332         ScreenPriv->CursorToRestore = NULL;
333         ScreenPriv->HotX = cursor->bits->xhot;
334         ScreenPriv->HotY = cursor->bits->yhot;
335 
336         if (!infoPtr->pScrn->vtSema) {
337             cursor = RefCursor(cursor);
338             if (ScreenPriv->SavedCursor)
339                 FreeCursor(ScreenPriv->SavedCursor, None);
340             ScreenPriv->SavedCursor = cursor;
341             return;
342         }
343 
344         if (infoPtr->pScrn->vtSema &&
345             (ScreenPriv->ForceHWCursorCount ||
346              xf86CheckHWCursor(pScreen, cursor, infoPtr))) {
347 
348             if (ScreenPriv->SWCursor)   /* remove the SW cursor */
349                 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
350                                                        NullCursor, x, y);
351 
352             if (xf86SetCursor(pScreen, cursor, x, y)) {
353                 ScreenPriv->SWCursor = FALSE;
354                 ScreenPriv->isUp = TRUE;
355 
356                 miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
357                 return;
358             }
359         }
360 
361         miPointerSetWaitForUpdate(pScreen, TRUE);
362 
363         if (ScreenPriv->isUp) {
364             /* Remove the HW cursor, or make it transparent */
365             if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) {
366                 xf86SetTransparentCursor(pScreen);
367             }
368             else {
369                 xf86SetCursor(pScreen, NullCursor, x, y);
370                 ScreenPriv->isUp = FALSE;
371             }
372         }
373 
374         if (!ScreenPriv->SWCursor)
375             ScreenPriv->SWCursor = TRUE;
376 
377     }
378 
379     if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
380         pCurs = NullCursor;
381 
382     (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCurs, x, y);
383 }
384 
385 /* Re-set the current cursor. This will switch between hardware and software
386  * cursor depending on whether hardware cursor is currently supported
387  * according to the driver.
388  */
389 void
xf86CursorResetCursor(ScreenPtr pScreen)390 xf86CursorResetCursor(ScreenPtr pScreen)
391 {
392     xf86CursorScreenPtr ScreenPriv;
393 
394     if (!inputInfo.pointer)
395         return;
396 
397     if (!dixPrivateKeyRegistered(xf86CursorScreenKey))
398         return;
399 
400     ScreenPriv = (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
401                                                         xf86CursorScreenKey);
402     if (!ScreenPriv)
403         return;
404 
405     xf86CursorSetCursor(inputInfo.pointer, pScreen, ScreenPriv->CurrentCursor,
406                         ScreenPriv->x, ScreenPriv->y);
407 }
408 
409 static void
xf86CursorMoveCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y)410 xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
411 {
412     xf86CursorScreenPtr ScreenPriv =
413         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
414                                                xf86CursorScreenKey);
415 
416     /* only update coordinate state for first sprite, otherwise we get jumps
417        when removing a sprite. The second sprite is never HW rendered anyway */
418     if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) {
419         ScreenPriv->x = x;
420         ScreenPriv->y = y;
421 
422         if (ScreenPriv->CursorToRestore)
423             xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x,
424                                 y);
425         else if (ScreenPriv->SWCursor)
426             (*ScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
427         else if (ScreenPriv->isUp)
428             xf86MoveCursor(pScreen, x, y);
429     }
430     else
431         (*ScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
432 }
433 
434 void
xf86ForceHWCursor(ScreenPtr pScreen,Bool on)435 xf86ForceHWCursor(ScreenPtr pScreen, Bool on)
436 {
437     DeviceIntPtr pDev = inputInfo.pointer;
438     xf86CursorScreenPtr ScreenPriv =
439         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
440                                                xf86CursorScreenKey);
441 
442     if (on) {
443         if (ScreenPriv->ForceHWCursorCount++ == 0) {
444             if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) {
445                 ScreenPriv->HWCursorForced = TRUE;
446                 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CurrentCursor,
447                                     ScreenPriv->x, ScreenPriv->y);
448             }
449             else
450                 ScreenPriv->HWCursorForced = FALSE;
451         }
452     }
453     else {
454         if (--ScreenPriv->ForceHWCursorCount == 0) {
455             if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor)
456                 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CurrentCursor,
457                                     ScreenPriv->x, ScreenPriv->y);
458         }
459     }
460 }
461 
462 CursorPtr
xf86CurrentCursor(ScreenPtr pScreen)463 xf86CurrentCursor(ScreenPtr pScreen)
464 {
465     xf86CursorScreenPtr ScreenPriv;
466 
467     if (pScreen->is_output_slave)
468         pScreen = pScreen->current_master;
469 
470     ScreenPriv = dixLookupPrivate(&pScreen->devPrivates, xf86CursorScreenKey);
471     return ScreenPriv->CurrentCursor;
472 }
473 
474 xf86CursorInfoPtr
xf86CreateCursorInfoRec(void)475 xf86CreateCursorInfoRec(void)
476 {
477     return calloc(1, sizeof(xf86CursorInfoRec));
478 }
479 
480 void
xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)481 xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)
482 {
483     free(infoPtr);
484 }
485 
486 /**
487  * New cursor has been created. Do your initalizations here.
488  */
489 static Bool
xf86DeviceCursorInitialize(DeviceIntPtr pDev,ScreenPtr pScreen)490 xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
491 {
492     int ret;
493     xf86CursorScreenPtr ScreenPriv =
494         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
495                                                xf86CursorScreenKey);
496 
497     /* Init SW cursor */
498     ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize) (pDev, pScreen);
499 
500     return ret;
501 }
502 
503 /**
504  * Cursor has been removed. Clean up after yourself.
505  */
506 static void
xf86DeviceCursorCleanup(DeviceIntPtr pDev,ScreenPtr pScreen)507 xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
508 {
509     xf86CursorScreenPtr ScreenPriv =
510         (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
511                                                xf86CursorScreenKey);
512 
513     /* Clean up SW cursor */
514     (*ScreenPriv->spriteFuncs->DeviceCursorCleanup) (pDev, pScreen);
515 }
516