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