1/* $NetBSD: wsfb_cursor.c,v 1.3 2011/05/15 23:44:47 christos Exp $ */
2/*
3 * Copyright (c) 2005 Michael Lorenz
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 *    - Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    - Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials provided
15 *      with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32/*
33 * Based on fbdev.c written by:
34 *
35 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
36 *	     Michel Dänzer, <michdaen@iiic.ethz.ch>
37 */
38
39#include <fcntl.h>
40#include <sys/types.h>
41#include <sys/time.h>
42#include <sys/endian.h>
43#include <dev/wscons/wsconsio.h>
44#include <errno.h>
45
46/* all driver need this */
47#include "xf86.h"
48#include "xf86_OSproc.h"
49#include "xf86_OSlib.h"
50
51#include "wsfb.h"
52
53static void WsfbLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
54static void WsfbSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
55static void WsfbSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
56
57static void
58WsfbLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
59{
60	WsfbPtr pWsfb = WSFBPTR(pScrn);
61	int err, i;
62
63	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOALL;
64	pWsfb->cursor.image = src;
65	pWsfb->cursor.mask = src + pWsfb->maskoffset;
66	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
67		xf86Msg(X_ERROR, "WsfbLoadCursorImage: %d\n", errno);
68}
69
70void
71WsfbShowCursor(ScrnInfoPtr pScrn)
72{
73	WsfbPtr pWsfb = WSFBPTR(pScrn);
74
75	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOCUR;
76	pWsfb->cursor.enable = 1;
77	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
78		xf86Msg(X_ERROR, "WsfbShowCursor: %d\n", errno);
79}
80
81void
82WsfbHideCursor(ScrnInfoPtr pScrn)
83{
84	WsfbPtr pWsfb = WSFBPTR(pScrn);
85
86	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOCUR;
87	pWsfb->cursor.enable = 0;
88	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
89		xf86Msg(X_ERROR, "WsfbHideCursor: %d\n", errno);
90}
91
92static void
93WsfbSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
94{
95	WsfbPtr pWsfb = WSFBPTR(pScrn);
96	int xoff = 0, yoff = 0;
97
98	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT;
99
100	if (x < 0) {
101		xoff = -x;
102		x = 0;
103	}
104	if (y < 0) {
105		yoff = -y;
106		y = 0;
107	}
108
109	pWsfb->cursor.pos.x = x;
110	pWsfb->cursor.hot.x = xoff;
111	pWsfb->cursor.pos.y = y;
112	pWsfb->cursor.hot.y = yoff;
113
114	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
115		xf86Msg(X_ERROR, "WsfbSetCursorPosition: %d\n", errno);
116}
117
118static void
119WsfbSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
120{
121	WsfbPtr pWsfb = WSFBPTR(pScrn);
122	u_char r[4], g[4], b[4];
123
124	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOCMAP;
125	pWsfb->cursor.cmap.red = r;
126	pWsfb->cursor.cmap.green = g;
127	pWsfb->cursor.cmap.blue = b;
128	r[1] = fg & 0xff;
129	g[1] = (fg & 0xff00) >> 8;
130	b[1] = (fg & 0xff0000) >> 16;
131	r[0] = bg & 0xff;
132	g[0] = (bg & 0xff00) >> 8;
133	b[0] = (bg & 0xff0000) >> 16;
134	pWsfb->cursor.cmap.index = 0;
135	pWsfb->cursor.cmap.count = 2;
136	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
137		xf86Msg(X_ERROR, "WsfbSetCursorColors: %d\n", errno);
138}
139
140Bool
141WsfbSetupCursor(ScreenPtr pScreen)
142{
143	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
144	WsfbPtr pWsfb = WSFBPTR(pScrn);
145	xf86CursorInfoPtr infoPtr;
146
147	pWsfb->cursor.pos.x = 0;
148	pWsfb->cursor.pos.y = 0;
149	pWsfb->cursor.enable = 0;
150
151	infoPtr = xf86CreateCursorInfoRec();
152	if(!infoPtr) return FALSE;
153
154	pWsfb->CursorInfoRec = infoPtr;
155	if(ioctl(pWsfb->fd, WSDISPLAYIO_GCURMAX, &pWsfb->cursor.size) == -1) {
156		xf86Msg(X_WARNING, "No HW cursor support found\n");
157		return FALSE;
158	}
159
160	xf86Msg(X_INFO, "HW cursor enabled\n");
161
162	infoPtr->MaxWidth = pWsfb->cursor.size.x;
163	infoPtr->MaxHeight = pWsfb->cursor.size.y;
164	pWsfb->maskoffset = ( pWsfb->cursor.size.x >> 3) * pWsfb->cursor.size.y;
165
166	pWsfb->cursor.hot.x = 0;
167	pWsfb->cursor.hot.y = 0;
168	pWsfb->cursor.which = WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCUR |
169	    WSDISPLAY_CURSOR_DOPOS;
170	if(ioctl(pWsfb->fd, WSDISPLAYIO_SCURSOR, &pWsfb->cursor) == -1)
171		xf86Msg(X_ERROR, "WSDISPLAYIO_SCURSOR: %d\n", errno);
172
173	infoPtr->Flags = HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
174	    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
175/* XXX not sure why exactly we need this */
176#if BYTE_ORDER == BIG_ENDIAN
177	    | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
178#endif
179	;
180	infoPtr->SetCursorColors = WsfbSetCursorColors;
181	infoPtr->SetCursorPosition = WsfbSetCursorPosition;
182	infoPtr->LoadCursorImage = WsfbLoadCursorImage;
183	infoPtr->HideCursor = WsfbHideCursor;
184	infoPtr->ShowCursor = WsfbShowCursor;
185	infoPtr->UseHWCursor = NULL;
186
187	return xf86InitCursor(pScreen, infoPtr);
188}
189