Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2007 Keith Packard | |
3 | * Copyright © 2010-2011 Aaron Plattner | |
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 copyright | |
8 | * notice and this permission notice appear in supporting documentation, and | |
9 | * that the name of the copyright holders not be used in advertising or | |
10 | * publicity pertaining to distribution of the software without specific, | |
11 | * written prior permission. The copyright holders make no representations | |
12 | * about the suitability of this software for any purpose. It is provided "as | |
13 | * is" without express or implied warranty. | |
14 | * | |
15 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
16 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
17 | * EVENT SHALL THE COPYRIGHT HOLDERS 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 PERFORMANCE | |
21 | * OF THIS SOFTWARE. | |
22 | */ | |
23 | ||
24 | #ifdef HAVE_XORG_CONFIG_H | |
25 | #include <xorg-config.h> | |
26 | #else | |
27 | #ifdef HAVE_CONFIG_H | |
28 | #include <config.h> | |
29 | #endif | |
30 | #endif | |
31 | ||
32 | #include <stddef.h> | |
33 | #include <string.h> | |
34 | #include <stdio.h> | |
35 | ||
36 | #include <X11/Xarch.h> | |
37 | #include "xf86.h" | |
38 | #include "xf86DDC.h" | |
39 | #include "xf86Crtc.h" | |
40 | #include "xf86Modes.h" | |
41 | #include "xf86RandR12.h" | |
42 | #include "xf86CursorPriv.h" | |
43 | #include "X11/extensions/render.h" | |
44 | #include "X11/extensions/dpmsconst.h" | |
45 | #include "X11/Xatom.h" | |
46 | #include "picturestr.h" | |
47 | #include "cursorstr.h" | |
48 | #include "inputstr.h" | |
49 | ||
50 | /* | |
51 | * Returns the rotation being performed by the server. If the driver indicates | |
52 | * that it's handling the screen transform, then this returns RR_Rotate_0. | |
53 | */ | |
54 | static Rotation | |
55 | xf86_crtc_cursor_rotation(xf86CrtcPtr crtc) | |
56 | { | |
57 | if (crtc->driverIsPerformingTransform) | |
58 | return RR_Rotate_0; | |
59 | return crtc->rotation; | |
60 | } | |
61 | ||
62 | /* | |
63 | * Given a screen coordinate, rotate back to a cursor source coordinate | |
64 | */ | |
65 | static void | |
66 | xf86_crtc_rotate_coord(Rotation rotation, | |
67 | int width, | |
68 | int height, int x_dst, int y_dst, int *x_src, int *y_src) | |
69 | { | |
70 | int t; | |
71 | ||
72 | switch (rotation & 0xf) { | |
73 | case RR_Rotate_0: | |
74 | break; | |
75 | case RR_Rotate_90: | |
76 | t = x_dst; | |
77 | x_dst = height - y_dst - 1; | |
78 | y_dst = t; | |
79 | break; | |
80 | case RR_Rotate_180: | |
81 | x_dst = width - x_dst - 1; | |
82 | y_dst = height - y_dst - 1; | |
83 | break; | |
84 | case RR_Rotate_270: | |
85 | t = x_dst; | |
86 | x_dst = y_dst; | |
87 | y_dst = width - t - 1; | |
88 | break; | |
89 | } | |
90 | if (rotation & RR_Reflect_X) | |
91 | x_dst = width - x_dst - 1; | |
92 | if (rotation & RR_Reflect_Y) | |
93 | y_dst = height - y_dst - 1; | |
94 | *x_src = x_dst; | |
95 | *y_src = y_dst; | |
96 | } | |
97 | ||
98 | /* | |
99 | * Given a cursor source coordinate, rotate to a screen coordinate | |
100 | */ | |
101 | static void | |
102 | xf86_crtc_rotate_coord_back(Rotation rotation, | |
103 | int width, | |
104 | int height, | |
105 | int x_dst, int y_dst, int *x_src, int *y_src) | |
106 | { | |
107 | int t; | |
108 | ||
109 | if (rotation & RR_Reflect_X) | |
110 | x_dst = width - x_dst - 1; | |
111 | if (rotation & RR_Reflect_Y) | |
112 | y_dst = height - y_dst - 1; | |
113 | ||
114 | switch (rotation & 0xf) { | |
115 | case RR_Rotate_0: | |
116 | break; | |
117 | case RR_Rotate_90: | |
118 | t = x_dst; | |
119 | x_dst = y_dst; | |
120 | y_dst = width - t - 1; | |
121 | break; | |
122 | case RR_Rotate_180: | |
123 | x_dst = width - x_dst - 1; | |
124 | y_dst = height - y_dst - 1; | |
125 | break; | |
126 | case RR_Rotate_270: | |
127 | t = x_dst; | |
128 | x_dst = height - y_dst - 1; | |
129 | y_dst = t; | |
130 | break; | |
131 | } | |
132 | *x_src = x_dst; | |
133 | *y_src = y_dst; | |
134 | } | |
135 | ||
136 | struct cursor_bit { | |
137 | CARD8 *byte; | |
138 | char bitpos; | |
139 | }; | |
140 | ||
141 | /* | |
142 | * Convert an x coordinate to a position within the cursor bitmap | |
143 | */ | |
144 | static struct cursor_bit | |
145 | cursor_bitpos(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, | |
146 | Bool mask) | |
147 | { | |
148 | const int flags = cursor_info->Flags; | |
149 | const Bool interleaved = | |
150 | ! !(flags & (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | | |
151 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 | | |
152 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 | | |
153 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | | |
154 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)); | |
155 | const int width = cursor_info->MaxWidth; | |
156 | const int height = cursor_info->MaxHeight; | |
157 | const int stride = interleaved ? width / 4 : width / 8; | |
158 | ||
159 | struct cursor_bit ret; | |
160 | ||
161 | image += y * stride; | |
162 | ||
163 | if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) | |
164 | mask = !mask; | |
165 | if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) | |
166 | x = (x & ~3) | (3 - (x & 3)); | |
167 | if (((flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) == 0) == | |
168 | (X_BYTE_ORDER == X_BIG_ENDIAN)) | |
169 | x = (x & ~7) | (7 - (x & 7)); | |
170 | if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1) | |
171 | x = (x << 1) + mask; | |
172 | else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8) | |
173 | x = ((x & ~7) << 1) | (mask << 3) | (x & 7); | |
174 | else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16) | |
175 | x = ((x & ~15) << 1) | (mask << 4) | (x & 15); | |
176 | else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32) | |
177 | x = ((x & ~31) << 1) | (mask << 5) | (x & 31); | |
178 | else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64) | |
179 | x = ((x & ~63) << 1) | (mask << 6) | (x & 63); | |
180 | else if (mask) | |
181 | image += stride * height; | |
182 | ||
183 | ret.byte = image + (x / 8); | |
184 | ret.bitpos = x & 7; | |
185 | ||
186 | return ret; | |
187 | } | |
188 | ||
189 | /* | |
190 | * Fetch one bit from a cursor bitmap | |
191 | */ | |
192 | static CARD8 | |
193 | get_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask) | |
194 | { | |
195 | struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask); | |
196 | ||
197 | return (*bit.byte >> bit.bitpos) & 1; | |
198 | } | |
199 | ||
200 | /* | |
201 | * Set one bit in a cursor bitmap | |
202 | */ | |
203 | static void | |
204 | set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask) | |
205 | { | |
206 | struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask); | |
207 | ||
208 | *bit.byte |= 1 << bit.bitpos; | |
209 | } | |
210 | ||
211 | /* | |
212 | * Load a two color cursor into a driver that supports only ARGB cursors | |
213 | */ | |
214 | static void | |
215 | xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src) | |
216 | { | |
217 | ScrnInfoPtr scrn = crtc->scrn; | |
218 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
219 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
220 | CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image; | |
221 | int x, y; | |
222 | int xin, yin; | |
223 | int flags = cursor_info->Flags; | |
224 | CARD32 bits; | |
225 | const Rotation rotation = xf86_crtc_cursor_rotation(crtc); | |
226 | ||
227 | #ifdef ARGB_CURSOR | |
228 | crtc->cursor_argb = FALSE; | |
229 | #endif | |
230 | ||
231 | for (y = 0; y < cursor_info->MaxHeight; y++) | |
232 | for (x = 0; x < cursor_info->MaxWidth; x++) { | |
233 | xf86_crtc_rotate_coord(rotation, | |
234 | cursor_info->MaxWidth, | |
235 | cursor_info->MaxHeight, x, y, &xin, &yin); | |
236 | if (get_bit(src, cursor_info, xin, yin, TRUE) == | |
237 | ((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) { | |
238 | if (get_bit(src, cursor_info, xin, yin, FALSE)) | |
239 | bits = xf86_config->cursor_fg; | |
240 | else | |
241 | bits = xf86_config->cursor_bg; | |
242 | } | |
243 | else | |
244 | bits = 0; | |
245 | cursor_image[y * cursor_info->MaxWidth + x] = bits; | |
246 | } | |
247 | crtc->funcs->load_cursor_argb(crtc, cursor_image); | |
248 | } | |
249 | ||
250 | /* | |
251 | * Set the colors for a two-color cursor (ignore for ARGB cursors) | |
252 | */ | |
253 | static void | |
254 | xf86_set_cursor_colors(ScrnInfoPtr scrn, int bg, int fg) | |
255 | { | |
256 | ScreenPtr screen = scrn->pScreen; | |
257 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
258 | CursorPtr cursor = xf86_config->cursor; | |
259 | int c; | |
260 | CARD8 *bits = cursor ? | |
261 | dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen) | |
262 | : NULL; | |
263 | ||
264 | /* Save ARGB versions of these colors */ | |
265 | xf86_config->cursor_fg = (CARD32) fg | 0xff000000; | |
266 | xf86_config->cursor_bg = (CARD32) bg | 0xff000000; | |
267 | ||
268 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
269 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
270 | ||
271 | if (crtc->enabled && !crtc->cursor_argb) { | |
272 | if (crtc->funcs->load_cursor_image) | |
273 | crtc->funcs->set_cursor_colors(crtc, bg, fg); | |
274 | else if (bits) | |
275 | xf86_crtc_convert_cursor_to_argb(crtc, bits); | |
276 | } | |
277 | } | |
278 | } | |
279 | ||
280 | static void | |
281 | xf86_crtc_hide_cursor(xf86CrtcPtr crtc) | |
282 | { | |
283 | if (crtc->cursor_shown) { | |
284 | crtc->funcs->hide_cursor(crtc); | |
285 | crtc->cursor_shown = FALSE; | |
286 | } | |
287 | } | |
288 | ||
289 | void | |
290 | xf86_hide_cursors(ScrnInfoPtr scrn) | |
291 | { | |
292 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
293 | int c; | |
294 | ||
295 | xf86_config->cursor_on = FALSE; | |
296 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
297 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
298 | ||
299 | if (crtc->enabled) | |
300 | xf86_crtc_hide_cursor(crtc); | |
301 | } | |
302 | } | |
303 | ||
304 | static void | |
305 | xf86_crtc_show_cursor(xf86CrtcPtr crtc) | |
306 | { | |
307 | if (!crtc->cursor_shown && crtc->cursor_in_range) { | |
308 | crtc->funcs->show_cursor(crtc); | |
309 | crtc->cursor_shown = TRUE; | |
310 | } | |
311 | } | |
312 | ||
313 | void | |
314 | xf86_show_cursors(ScrnInfoPtr scrn) | |
315 | { | |
316 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
317 | int c; | |
318 | ||
319 | xf86_config->cursor_on = TRUE; | |
320 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
321 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
322 | ||
323 | if (crtc->enabled) | |
324 | xf86_crtc_show_cursor(crtc); | |
325 | } | |
326 | } | |
327 | ||
328 | void | |
329 | xf86CrtcTransformCursorPos(xf86CrtcPtr crtc, int *x, int *y) | |
330 | { | |
331 | ScrnInfoPtr scrn = crtc->scrn; | |
332 | ScreenPtr screen = scrn->pScreen; | |
333 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
334 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
335 | xf86CursorScreenPtr ScreenPriv = | |
336 | (xf86CursorScreenPtr) dixLookupPrivate(&screen->devPrivates, | |
337 | xf86CursorScreenKey); | |
338 | struct pict_f_vector v; | |
339 | int dx, dy; | |
340 | ||
341 | v.v[0] = (*x + ScreenPriv->HotX) + 0.5; | |
342 | v.v[1] = (*y + ScreenPriv->HotY) + 0.5; | |
343 | v.v[2] = 1; | |
344 | pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &v); | |
345 | /* cursor will have 0.5 added to it already so floor is sufficent */ | |
346 | *x = floor(v.v[0]); | |
347 | *y = floor(v.v[1]); | |
348 | /* | |
349 | * Transform position of cursor upper left corner | |
350 | */ | |
351 | xf86_crtc_rotate_coord_back(crtc->rotation, cursor_info->MaxWidth, | |
352 | cursor_info->MaxHeight, ScreenPriv->HotX, | |
353 | ScreenPriv->HotY, &dx, &dy); | |
354 | *x -= dx; | |
355 | *y -= dy; | |
356 | } | |
357 | ||
358 | static void | |
359 | xf86_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) | |
360 | { | |
361 | ScrnInfoPtr scrn = crtc->scrn; | |
362 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
363 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
364 | DisplayModePtr mode = &crtc->mode; | |
365 | Bool in_range; | |
366 | ||
367 | /* | |
368 | * Transform position of cursor on screen | |
369 | */ | |
370 | if (crtc->transform_in_use && !crtc->driverIsPerformingTransform) | |
371 | xf86CrtcTransformCursorPos(crtc, &x, &y); | |
372 | else { | |
373 | x -= crtc->x; | |
374 | y -= crtc->y; | |
375 | } | |
376 | ||
377 | /* | |
378 | * Disable the cursor when it is outside the viewport | |
379 | */ | |
380 | in_range = TRUE; | |
381 | if (x >= mode->HDisplay || y >= mode->VDisplay || | |
382 | x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) { | |
383 | in_range = FALSE; | |
384 | x = 0; | |
385 | y = 0; | |
386 | } | |
387 | ||
388 | crtc->cursor_in_range = in_range; | |
389 | ||
390 | if (in_range) { | |
391 | crtc->funcs->set_cursor_position(crtc, x, y); | |
392 | xf86_crtc_show_cursor(crtc); | |
393 | } | |
394 | else | |
395 | xf86_crtc_hide_cursor(crtc); | |
396 | } | |
397 | ||
398 | static void | |
399 | xf86_set_cursor_position(ScrnInfoPtr scrn, int x, int y) | |
400 | { | |
401 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
402 | int c; | |
403 | ||
404 | /* undo what xf86HWCurs did to the coordinates */ | |
405 | x += scrn->frameX0; | |
406 | y += scrn->frameY0; | |
407 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
408 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
409 | ||
410 | if (crtc->enabled) | |
411 | xf86_crtc_set_cursor_position(crtc, x, y); | |
412 | } | |
413 | } | |
414 | ||
415 | /* | |
416 | * Load a two-color cursor into a crtc, performing rotation as needed | |
417 | */ | |
418 | static void | |
419 | xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src) | |
420 | { | |
421 | ScrnInfoPtr scrn = crtc->scrn; | |
422 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
423 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
424 | CARD8 *cursor_image; | |
425 | const Rotation rotation = xf86_crtc_cursor_rotation(crtc); | |
426 | ||
427 | #ifdef ARGB_CURSOR | |
428 | crtc->cursor_argb = FALSE; | |
429 | #endif | |
430 | ||
431 | if (rotation == RR_Rotate_0) | |
432 | cursor_image = src; | |
433 | else { | |
434 | int x, y; | |
435 | int xin, yin; | |
436 | int stride = cursor_info->MaxWidth >> 2; | |
437 | ||
438 | cursor_image = xf86_config->cursor_image; | |
439 | memset(cursor_image, 0, cursor_info->MaxHeight * stride); | |
440 | ||
441 | for (y = 0; y < cursor_info->MaxHeight; y++) | |
442 | for (x = 0; x < cursor_info->MaxWidth; x++) { | |
443 | xf86_crtc_rotate_coord(rotation, | |
444 | cursor_info->MaxWidth, | |
445 | cursor_info->MaxHeight, | |
446 | x, y, &xin, &yin); | |
447 | if (get_bit(src, cursor_info, xin, yin, FALSE)) | |
448 | set_bit(cursor_image, cursor_info, x, y, FALSE); | |
449 | if (get_bit(src, cursor_info, xin, yin, TRUE)) | |
450 | set_bit(cursor_image, cursor_info, x, y, TRUE); | |
451 | } | |
452 | } | |
453 | crtc->funcs->load_cursor_image(crtc, cursor_image); | |
454 | } | |
455 | ||
456 | /* | |
457 | * Load a cursor image into all active CRTCs | |
458 | */ | |
459 | static void | |
460 | xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src) | |
461 | { | |
462 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
463 | int c; | |
464 | ||
465 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
466 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
467 | ||
468 | if (crtc->enabled) { | |
469 | if (crtc->funcs->load_cursor_image) | |
470 | xf86_crtc_load_cursor_image(crtc, src); | |
471 | else if (crtc->funcs->load_cursor_argb) | |
472 | xf86_crtc_convert_cursor_to_argb(crtc, src); | |
473 | } | |
474 | } | |
475 | } | |
476 | ||
477 | static Bool | |
478 | xf86_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) | |
479 | { | |
480 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | |
481 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
482 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
483 | ||
484 | cursor = RefCursor(cursor); | |
485 | if (xf86_config->cursor) | |
486 | FreeCursor(xf86_config->cursor, None); | |
487 | xf86_config->cursor = cursor; | |
488 | ||
489 | if (cursor->bits->width > cursor_info->MaxWidth || | |
490 | cursor->bits->height > cursor_info->MaxHeight) | |
491 | return FALSE; | |
492 | ||
493 | return TRUE; | |
494 | } | |
495 | ||
496 | static Bool | |
497 | xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor) | |
498 | { | |
499 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | |
500 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
501 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
502 | ||
503 | cursor = RefCursor(cursor); | |
504 | if (xf86_config->cursor) | |
505 | FreeCursor(xf86_config->cursor, None); | |
506 | xf86_config->cursor = cursor; | |
507 | ||
508 | /* Make sure ARGB support is available */ | |
509 | if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0) | |
510 | return FALSE; | |
511 | ||
512 | if (cursor->bits->width > cursor_info->MaxWidth || | |
513 | cursor->bits->height > cursor_info->MaxHeight) | |
514 | return FALSE; | |
515 | ||
516 | return TRUE; | |
517 | } | |
518 | ||
519 | static void | |
520 | xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor) | |
521 | { | |
522 | ScrnInfoPtr scrn = crtc->scrn; | |
523 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
524 | xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; | |
525 | CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image; | |
526 | CARD32 *cursor_source = (CARD32 *) cursor->bits->argb; | |
527 | int x, y; | |
528 | int xin, yin; | |
529 | CARD32 bits; | |
530 | int source_width = cursor->bits->width; | |
531 | int source_height = cursor->bits->height; | |
532 | int image_width = cursor_info->MaxWidth; | |
533 | int image_height = cursor_info->MaxHeight; | |
534 | const Rotation rotation = xf86_crtc_cursor_rotation(crtc); | |
535 | ||
536 | for (y = 0; y < image_height; y++) | |
537 | for (x = 0; x < image_width; x++) { | |
538 | xf86_crtc_rotate_coord(rotation, image_width, image_height, x, y, | |
539 | &xin, &yin); | |
540 | if (xin < source_width && yin < source_height) | |
541 | bits = cursor_source[yin * source_width + xin]; | |
542 | else | |
543 | bits = 0; | |
544 | cursor_image[y * image_width + x] = bits; | |
545 | } | |
546 | ||
547 | crtc->funcs->load_cursor_argb(crtc, cursor_image); | |
548 | } | |
549 | ||
550 | static void | |
551 | xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor) | |
552 | { | |
553 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
554 | int c; | |
555 | ||
556 | for (c = 0; c < xf86_config->num_crtc; c++) { | |
557 | xf86CrtcPtr crtc = xf86_config->crtc[c]; | |
558 | ||
559 | if (crtc->enabled) | |
560 | xf86_crtc_load_cursor_argb(crtc, cursor); | |
561 | } | |
562 | } | |
563 | ||
564 | Bool | |
565 | xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags) | |
566 | { | |
567 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | |
568 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
569 | xf86CursorInfoPtr cursor_info; | |
570 | ||
571 | cursor_info = xf86CreateCursorInfoRec(); | |
572 | if (!cursor_info) | |
573 | return FALSE; | |
574 | ||
575 | xf86_config->cursor_image = malloc(max_width * max_height * 4); | |
576 | ||
577 | if (!xf86_config->cursor_image) { | |
578 | xf86DestroyCursorInfoRec(cursor_info); | |
579 | return FALSE; | |
580 | } | |
581 | ||
582 | xf86_config->cursor_info = cursor_info; | |
583 | ||
584 | cursor_info->MaxWidth = max_width; | |
585 | cursor_info->MaxHeight = max_height; | |
586 | cursor_info->Flags = flags; | |
587 | ||
588 | cursor_info->SetCursorColors = xf86_set_cursor_colors; | |
589 | cursor_info->SetCursorPosition = xf86_set_cursor_position; | |
590 | cursor_info->LoadCursorImage = xf86_load_cursor_image; | |
591 | cursor_info->HideCursor = xf86_hide_cursors; | |
592 | cursor_info->ShowCursor = xf86_show_cursors; | |
593 | cursor_info->UseHWCursor = xf86_use_hw_cursor; | |
594 | #ifdef ARGB_CURSOR | |
595 | if (flags & HARDWARE_CURSOR_ARGB) { | |
596 | cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb; | |
597 | cursor_info->LoadCursorARGB = xf86_load_cursor_argb; | |
598 | } | |
599 | #endif | |
600 | ||
601 | xf86_config->cursor = NULL; | |
602 | xf86_hide_cursors(scrn); | |
603 | ||
604 | return xf86InitCursor(screen, cursor_info); | |
605 | } | |
606 | ||
607 | /** | |
608 | * Called when anything on the screen is reconfigured. | |
609 | * | |
610 | * Reloads cursor images as needed, then adjusts cursor positions | |
611 | */ | |
612 | ||
613 | void | |
614 | xf86_reload_cursors(ScreenPtr screen) | |
615 | { | |
616 | ScrnInfoPtr scrn; | |
617 | xf86CrtcConfigPtr xf86_config; | |
618 | xf86CursorInfoPtr cursor_info; | |
619 | CursorPtr cursor; | |
620 | int x, y; | |
621 | xf86CursorScreenPtr cursor_screen_priv; | |
622 | ||
623 | /* initial mode setting will not have set a screen yet. | |
624 | May be called before the devices are initialised. | |
625 | */ | |
626 | if (!screen || !inputInfo.pointer) | |
627 | return; | |
628 | cursor_screen_priv = dixLookupPrivate(&screen->devPrivates, | |
629 | xf86CursorScreenKey); | |
630 | /* return if HW cursor is inactive, to avoid displaying two cursors */ | |
631 | if (!cursor_screen_priv || !cursor_screen_priv->isUp) | |
632 | return; | |
633 | ||
634 | scrn = xf86ScreenToScrn(screen); | |
635 | xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
636 | ||
637 | /* make sure the cursor code has been initialized */ | |
638 | cursor_info = xf86_config->cursor_info; | |
639 | if (!cursor_info) | |
640 | return; | |
641 | ||
642 | cursor = xf86_config->cursor; | |
643 | GetSpritePosition(inputInfo.pointer, &x, &y); | |
644 | if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) | |
645 | (*cursor_info->HideCursor) (scrn); | |
646 | ||
647 | if (cursor) { | |
648 | void *src = | |
649 | dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, | |
650 | screen); | |
651 | #ifdef ARGB_CURSOR | |
652 | if (cursor->bits->argb && cursor_info->LoadCursorARGB) | |
653 | (*cursor_info->LoadCursorARGB) (scrn, cursor); | |
654 | else if (src) | |
655 | #endif | |
656 | (*cursor_info->LoadCursorImage) (scrn, src); | |
657 | ||
658 | x += scrn->frameX0 + cursor_screen_priv->HotX; | |
659 | y += scrn->frameY0 + cursor_screen_priv->HotY; | |
660 | (*cursor_info->SetCursorPosition) (scrn, x, y); | |
661 | } | |
662 | } | |
663 | ||
664 | /** | |
665 | * Clean up CRTC-based cursor code | |
666 | */ | |
667 | void | |
668 | xf86_cursors_fini(ScreenPtr screen) | |
669 | { | |
670 | ScrnInfoPtr scrn = xf86ScreenToScrn(screen); | |
671 | xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); | |
672 | ||
673 | if (xf86_config->cursor_info) { | |
674 | xf86DestroyCursorInfoRec(xf86_config->cursor_info); | |
675 | xf86_config->cursor_info = NULL; | |
676 | } | |
677 | free(xf86_config->cursor_image); | |
678 | xf86_config->cursor_image = NULL; | |
679 | if (xf86_config->cursor) { | |
680 | FreeCursor(xf86_config->cursor, None); | |
681 | xf86_config->cursor = NULL; | |
682 | } | |
683 | } |