Add patch that contain Mali fixes.
[deb_xorg-server.git] / render / animcur.c
1 /*
2 *
3 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24 /*
25 * Animated cursors for X. Not specific to Render in any way, but
26 * stuck there because Render has the other cool cursor extension.
27 * Besides, everyone has Render.
28 *
29 * Implemented as a simple layer over the core cursor code; it
30 * creates composite cursors out of a set of static cursors and
31 * delta times between each image.
32 */
33
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
36 #endif
37
38 #include <X11/X.h>
39 #include <X11/Xmd.h>
40 #include "servermd.h"
41 #include "scrnintstr.h"
42 #include "dixstruct.h"
43 #include "cursorstr.h"
44 #include "dixfontstr.h"
45 #include "opaque.h"
46 #include "picturestr.h"
47 #include "inputstr.h"
48 #include "xace.h"
49
50 typedef struct _AnimCurElt {
51 CursorPtr pCursor; /* cursor to show */
52 CARD32 delay; /* in ms */
53 } AnimCurElt;
54
55 typedef struct _AnimCur {
56 int nelt; /* number of elements in the elts array */
57 AnimCurElt *elts; /* actually allocated right after the structure */
58 } AnimCurRec, *AnimCurPtr;
59
60 typedef struct _AnimScrPriv {
61 CloseScreenProcPtr CloseScreen;
62
63 ScreenBlockHandlerProcPtr BlockHandler;
64
65 CursorLimitsProcPtr CursorLimits;
66 DisplayCursorProcPtr DisplayCursor;
67 SetCursorPositionProcPtr SetCursorPosition;
68 RealizeCursorProcPtr RealizeCursor;
69 UnrealizeCursorProcPtr UnrealizeCursor;
70 RecolorCursorProcPtr RecolorCursor;
71 } AnimCurScreenRec, *AnimCurScreenPtr;
72
73 static unsigned char empty[4];
74
75 static CursorBits animCursorBits = {
76 empty, empty, 2, 1, 1, 0, 0, 1
77 };
78
79 static DevPrivateKeyRec AnimCurScreenPrivateKeyRec;
80
81 #define AnimCurScreenPrivateKey (&AnimCurScreenPrivateKeyRec)
82
83 #define IsAnimCur(c) ((c) && ((c)->bits == &animCursorBits))
84 #define GetAnimCur(c) ((AnimCurPtr) ((((char *)(c) + CURSOR_REC_SIZE))))
85 #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey))
86 #define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p)
87
88 #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
89 #define Unwrap(as,s,elt) ((s)->elt = (as)->elt)
90
91 static Bool
92 AnimCurCloseScreen(ScreenPtr pScreen)
93 {
94 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
95 Bool ret;
96
97 Unwrap(as, pScreen, CloseScreen);
98
99 Unwrap(as, pScreen, CursorLimits);
100 Unwrap(as, pScreen, DisplayCursor);
101 Unwrap(as, pScreen, SetCursorPosition);
102 Unwrap(as, pScreen, RealizeCursor);
103 Unwrap(as, pScreen, UnrealizeCursor);
104 Unwrap(as, pScreen, RecolorCursor);
105 SetAnimCurScreen(pScreen, 0);
106 ret = (*pScreen->CloseScreen) (pScreen);
107 free(as);
108 return ret;
109 }
110
111 static void
112 AnimCurCursorLimits(DeviceIntPtr pDev,
113 ScreenPtr pScreen,
114 CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox)
115 {
116 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
117
118 Unwrap(as, pScreen, CursorLimits);
119 if (IsAnimCur(pCursor)) {
120 AnimCurPtr ac = GetAnimCur(pCursor);
121
122 (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor,
123 pHotBox, pTopLeftBox);
124 }
125 else {
126 (*pScreen->CursorLimits) (pDev, pScreen, pCursor, pHotBox, pTopLeftBox);
127 }
128 Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits);
129 }
130
131 /*
132 * This has to be a screen block handler instead of a generic
133 * block handler so that it is well ordered with respect to the DRI
134 * block handler responsible for releasing the hardware to DRI clients
135 */
136
137 static void
138 AnimCurScreenBlockHandler(ScreenPtr pScreen,
139 pointer pTimeout, pointer pReadmask)
140 {
141 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
142 DeviceIntPtr dev;
143 Bool activeDevice = FALSE;
144 CARD32 now = 0, soonest = ~0; /* earliest time to wakeup again */
145
146 Unwrap(as, pScreen, BlockHandler);
147
148 for (dev = inputInfo.devices; dev; dev = dev->next) {
149 if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen) {
150 if (!activeDevice) {
151 now = GetTimeInMillis();
152 activeDevice = TRUE;
153 }
154
155 if ((INT32) (now - dev->spriteInfo->anim.time) >= 0) {
156 AnimCurPtr ac = GetAnimCur(dev->spriteInfo->anim.pCursor);
157 int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt;
158 DisplayCursorProcPtr DisplayCursor;
159
160 /*
161 * Not a simple Unwrap/Wrap as this
162 * isn't called along the DisplayCursor
163 * wrapper chain.
164 */
165 DisplayCursor = pScreen->DisplayCursor;
166 pScreen->DisplayCursor = as->DisplayCursor;
167 (void) (*pScreen->DisplayCursor) (dev,
168 pScreen,
169 ac->elts[elt].pCursor);
170 as->DisplayCursor = pScreen->DisplayCursor;
171 pScreen->DisplayCursor = DisplayCursor;
172
173 dev->spriteInfo->anim.elt = elt;
174 dev->spriteInfo->anim.time = now + ac->elts[elt].delay;
175 }
176
177 if (soonest > dev->spriteInfo->anim.time)
178 soonest = dev->spriteInfo->anim.time;
179 }
180 }
181
182 if (activeDevice)
183 AdjustWaitForDelay(pTimeout, soonest - now);
184
185 (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
186 if (activeDevice)
187 Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
188 else
189 as->BlockHandler = NULL;
190 }
191
192 static Bool
193 AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
194 {
195 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
196 Bool ret;
197
198 if (IsFloating(pDev))
199 return FALSE;
200
201 Unwrap(as, pScreen, DisplayCursor);
202 if (IsAnimCur(pCursor)) {
203 if (pCursor != pDev->spriteInfo->anim.pCursor) {
204 AnimCurPtr ac = GetAnimCur(pCursor);
205
206 ret = (*pScreen->DisplayCursor)
207 (pDev, pScreen, ac->elts[0].pCursor);
208 if (ret) {
209 pDev->spriteInfo->anim.elt = 0;
210 pDev->spriteInfo->anim.time =
211 GetTimeInMillis() + ac->elts[0].delay;
212 pDev->spriteInfo->anim.pCursor = pCursor;
213 pDev->spriteInfo->anim.pScreen = pScreen;
214
215 if (!as->BlockHandler)
216 Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
217 }
218 }
219 else
220 ret = TRUE;
221 }
222 else {
223 pDev->spriteInfo->anim.pCursor = 0;
224 pDev->spriteInfo->anim.pScreen = 0;
225 ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
226 }
227 Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
228 return ret;
229 }
230
231 static Bool
232 AnimCurSetCursorPosition(DeviceIntPtr pDev,
233 ScreenPtr pScreen, int x, int y, Bool generateEvent)
234 {
235 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
236 Bool ret;
237
238 Unwrap(as, pScreen, SetCursorPosition);
239 if (pDev->spriteInfo->anim.pCursor) {
240 pDev->spriteInfo->anim.pScreen = pScreen;
241
242 if (!as->BlockHandler)
243 Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
244 }
245 ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
246 Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
247 return ret;
248 }
249
250 static Bool
251 AnimCurRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
252 {
253 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
254 Bool ret;
255
256 Unwrap(as, pScreen, RealizeCursor);
257 if (IsAnimCur(pCursor))
258 ret = TRUE;
259 else
260 ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor);
261 Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor);
262 return ret;
263 }
264
265 static Bool
266 AnimCurUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
267 {
268 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
269 Bool ret;
270
271 Unwrap(as, pScreen, UnrealizeCursor);
272 if (IsAnimCur(pCursor)) {
273 AnimCurPtr ac = GetAnimCur(pCursor);
274 int i;
275
276 if (pScreen->myNum == 0)
277 for (i = 0; i < ac->nelt; i++)
278 FreeCursor(ac->elts[i].pCursor, 0);
279 ret = TRUE;
280 }
281 else
282 ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
283 Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
284 return ret;
285 }
286
287 static void
288 AnimCurRecolorCursor(DeviceIntPtr pDev,
289 ScreenPtr pScreen, CursorPtr pCursor, Bool displayed)
290 {
291 AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
292
293 Unwrap(as, pScreen, RecolorCursor);
294 if (IsAnimCur(pCursor)) {
295 AnimCurPtr ac = GetAnimCur(pCursor);
296 int i;
297
298 for (i = 0; i < ac->nelt; i++)
299 (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
300 displayed &&
301 pDev->spriteInfo->anim.elt == i);
302 }
303 else
304 (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
305 Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor);
306 }
307
308 Bool
309 AnimCurInit(ScreenPtr pScreen)
310 {
311 AnimCurScreenPtr as;
312
313 if (!dixRegisterPrivateKey(&AnimCurScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
314 return FALSE;
315
316 as = (AnimCurScreenPtr) malloc(sizeof(AnimCurScreenRec));
317 if (!as)
318 return FALSE;
319 Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen);
320
321 as->BlockHandler = NULL;
322
323 Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits);
324 Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
325 Wrap(as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
326 Wrap(as, pScreen, RealizeCursor, AnimCurRealizeCursor);
327 Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
328 Wrap(as, pScreen, RecolorCursor, AnimCurRecolorCursor);
329 SetAnimCurScreen(pScreen, as);
330 return TRUE;
331 }
332
333 int
334 AnimCursorCreate(CursorPtr *cursors, CARD32 *deltas, int ncursor,
335 CursorPtr *ppCursor, ClientPtr client, XID cid)
336 {
337 CursorPtr pCursor;
338 int rc, i;
339 AnimCurPtr ac;
340
341 for (i = 0; i < screenInfo.numScreens; i++)
342 if (!GetAnimCurScreen(screenInfo.screens[i]))
343 return BadImplementation;
344
345 for (i = 0; i < ncursor; i++)
346 if (IsAnimCur(cursors[i]))
347 return BadMatch;
348
349 pCursor = (CursorPtr) calloc(CURSOR_REC_SIZE +
350 sizeof(AnimCurRec) +
351 ncursor * sizeof(AnimCurElt), 1);
352 if (!pCursor)
353 return BadAlloc;
354 dixInitPrivates(pCursor, pCursor + 1, PRIVATE_CURSOR);
355 pCursor->bits = &animCursorBits;
356 pCursor->refcnt = 1;
357
358 pCursor->foreRed = cursors[0]->foreRed;
359 pCursor->foreGreen = cursors[0]->foreGreen;
360 pCursor->foreBlue = cursors[0]->foreBlue;
361
362 pCursor->backRed = cursors[0]->backRed;
363 pCursor->backGreen = cursors[0]->backGreen;
364 pCursor->backBlue = cursors[0]->backBlue;
365
366 pCursor->id = cid;
367
368 /* security creation/labeling check */
369 rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, pCursor,
370 RT_NONE, NULL, DixCreateAccess);
371 if (rc != Success) {
372 dixFiniPrivates(pCursor, PRIVATE_CURSOR);
373 free(pCursor);
374 return rc;
375 }
376
377 /*
378 * Fill in the AnimCurRec
379 */
380 animCursorBits.refcnt++;
381 ac = GetAnimCur(pCursor);
382 ac->nelt = ncursor;
383 ac->elts = (AnimCurElt *) (ac + 1);
384
385 for (i = 0; i < ncursor; i++) {
386 ac->elts[i].pCursor = RefCursor(cursors[i]);
387 ac->elts[i].delay = deltas[i];
388 }
389
390 *ppCursor = pCursor;
391 return Success;
392 }