Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / ramdac / xf86Cursor.c
CommitLineData
a09e091a
JB
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
20DevPrivateKeyRec xf86CursorScreenKeyRec;
21
22/* sprite functions */
23
24static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
25static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
26static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
27static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
28static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr);
29static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr);
30
31static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
32 xf86CursorRealizeCursor,
33 xf86CursorUnrealizeCursor,
34 xf86CursorSetCursor,
35 xf86CursorMoveCursor,
36 xf86DeviceCursorInitialize,
37 xf86DeviceCursorCleanup
38};
39
40/* Screen functions */
41
42static void xf86CursorInstallColormap(ColormapPtr);
43static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr,
44 Bool);
45static Bool xf86CursorCloseScreen(ScreenPtr);
46static void xf86CursorQueryBestSize(int, unsigned short *, unsigned short *,
47 ScreenPtr);
48
49/* ScrnInfoRec functions */
50
51static void xf86CursorEnableDisableFBAccess(ScrnInfoPtr, Bool);
52static Bool xf86CursorSwitchMode(ScrnInfoPtr, DisplayModePtr);
53
54Bool
55xf86InitCursor(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
119static Bool
120xf86CursorCloseScreen(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
154static void
155xf86CursorQueryBestSize(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
173static void
174xf86CursorInstallColormap(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
185static void
186xf86CursorRecolorCursor(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
204static void
205xf86CursorEnableDisableFBAccess(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 = 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 ScreenPriv->SavedCursor = NULL;
235 }
236}
237
238static Bool
239xf86CursorSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
240{
241 Bool ret;
242 ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
243 xf86CursorScreenPtr ScreenPriv =
244 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
245 xf86CursorScreenKey);
246
247 if (ScreenPriv->isUp) {
248 xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
249 ScreenPriv->isUp = FALSE;
250 }
251
252 ret = (*ScreenPriv->SwitchMode) (pScrn, mode);
253
254 /*
255 * Cannot restore cursor here because the new frame[XY][01] haven't been
256 * calculated yet. However, because the hardware cursor was removed above,
257 * ensure the cursor is repainted by miPointerWarpCursor().
258 */
259 ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor;
260 miPointerSetWaitForUpdate(pScreen, FALSE); /* Force cursor repaint */
261
262 return ret;
263}
264
265/****** miPointerSpriteFunctions *******/
266
267static Bool
268xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
269{
270 xf86CursorScreenPtr ScreenPriv =
271 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
272 xf86CursorScreenKey);
273
274 if (CursorRefCount(pCurs) <= 1)
275 dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
276 NULL);
277
278 return (*ScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCurs);
279}
280
281static Bool
282xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
283{
284 xf86CursorScreenPtr ScreenPriv =
285 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
286 xf86CursorScreenKey);
287
288 if (CursorRefCount(pCurs) <= 1) {
289 free(dixLookupScreenPrivate
290 (&pCurs->devPrivates, CursorScreenKey, pScreen));
291 dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
292 NULL);
293 }
294
295 return (*ScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCurs);
296}
297
298static void
299xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
300 int x, int y)
301{
302 xf86CursorScreenPtr ScreenPriv =
303 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
304 xf86CursorScreenKey);
305 xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
306
307 if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */
308 if (ScreenPriv->SWCursor ||
309 !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer))
310 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, NullCursor, x,
311 y);
312 else if (ScreenPriv->isUp) {
313 xf86SetCursor(pScreen, NullCursor, x, y);
314 ScreenPriv->isUp = FALSE;
315 }
316 if (ScreenPriv->CurrentCursor)
317 FreeCursor(ScreenPriv->CurrentCursor, None);
318 ScreenPriv->CurrentCursor = NullCursor;
319 return;
320 }
321
322 /* only update for VCP, otherwise we get cursor jumps when removing a
323 sprite. The second cursor is never HW rendered anyway. */
324 if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) {
325 CursorPtr cursor = RefCursor(pCurs);
326 if (ScreenPriv->CurrentCursor)
327 FreeCursor(ScreenPriv->CurrentCursor, None);
328 ScreenPriv->CurrentCursor = cursor;
329 ScreenPriv->x = x;
330 ScreenPriv->y = y;
331 ScreenPriv->CursorToRestore = NULL;
332 ScreenPriv->HotX = cursor->bits->xhot;
333 ScreenPriv->HotY = cursor->bits->yhot;
334
335 if (!infoPtr->pScrn->vtSema)
336 ScreenPriv->SavedCursor = cursor;
337
338 if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) &&
339 (ScreenPriv->ForceHWCursorCount ||
340 ((
341#ifdef ARGB_CURSOR
342 cursor->bits->argb &&
343 infoPtr->UseHWCursorARGB &&
344 (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) ||
345 (cursor->bits->argb == 0 &&
346#endif
347 (cursor->bits->height <= infoPtr->MaxHeight) &&
348 (cursor->bits->width <= infoPtr->MaxWidth) &&
349 (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) {
350
351 if (ScreenPriv->SWCursor) /* remove the SW cursor */
352 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
353 NullCursor, x, y);
354
355 xf86SetCursor(pScreen, cursor, x, y);
356 ScreenPriv->SWCursor = FALSE;
357 ScreenPriv->isUp = TRUE;
358
359 miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
360 return;
361 }
362
363 miPointerSetWaitForUpdate(pScreen, TRUE);
364
365 if (ScreenPriv->isUp) {
366 /* Remove the HW cursor, or make it transparent */
367 if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) {
368 xf86SetTransparentCursor(pScreen);
369 }
370 else {
371 xf86SetCursor(pScreen, NullCursor, x, y);
372 ScreenPriv->isUp = FALSE;
373 }
374 }
375
376 if (!ScreenPriv->SWCursor)
377 ScreenPriv->SWCursor = TRUE;
378
379 }
380
381 if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
382 pCurs = NullCursor;
383
384 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCurs, x, y);
385}
386
387static void
388xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
389{
390 xf86CursorScreenPtr ScreenPriv =
391 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
392 xf86CursorScreenKey);
393
394 /* only update coordinate state for first sprite, otherwise we get jumps
395 when removing a sprite. The second sprite is never HW rendered anyway */
396 if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) {
397 ScreenPriv->x = x;
398 ScreenPriv->y = y;
399
400 if (ScreenPriv->CursorToRestore)
401 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x,
402 y);
403 else if (ScreenPriv->SWCursor)
404 (*ScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
405 else if (ScreenPriv->isUp)
406 xf86MoveCursor(pScreen, x, y);
407 }
408 else
409 (*ScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
410}
411
412void
413xf86ForceHWCursor(ScreenPtr pScreen, Bool on)
414{
415 DeviceIntPtr pDev = inputInfo.pointer;
416 xf86CursorScreenPtr ScreenPriv =
417 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
418 xf86CursorScreenKey);
419
420 if (on) {
421 if (ScreenPriv->ForceHWCursorCount++ == 0) {
422 if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) {
423 ScreenPriv->HWCursorForced = TRUE;
424 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CurrentCursor,
425 ScreenPriv->x, ScreenPriv->y);
426 }
427 else
428 ScreenPriv->HWCursorForced = FALSE;
429 }
430 }
431 else {
432 if (--ScreenPriv->ForceHWCursorCount == 0) {
433 if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor)
434 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CurrentCursor,
435 ScreenPriv->x, ScreenPriv->y);
436 }
437 }
438}
439
440xf86CursorInfoPtr
441xf86CreateCursorInfoRec(void)
442{
443 return calloc(1, sizeof(xf86CursorInfoRec));
444}
445
446void
447xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)
448{
449 free(infoPtr);
450}
451
452/**
453 * New cursor has been created. Do your initalizations here.
454 */
455static Bool
456xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
457{
458 int ret;
459 xf86CursorScreenPtr ScreenPriv =
460 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
461 xf86CursorScreenKey);
462
463 /* Init SW cursor */
464 ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize) (pDev, pScreen);
465
466 return ret;
467}
468
469/**
470 * Cursor has been removed. Clean up after yourself.
471 */
472static void
473xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
474{
475 xf86CursorScreenPtr ScreenPriv =
476 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
477 xf86CursorScreenKey);
478
479 /* Clean up SW cursor */
480 (*ScreenPriv->spriteFuncs->DeviceCursorCleanup) (pDev, pScreen);
481}