1/* $NetBSD: mgx_cursor.c,v 1.1 2021/11/12 18:58:14 macallan 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 * fugly copypasta for now
34 * the mgx at sbus driver lets us run wsdisplay ioctl()s on the fb device
35 * will replace with direct hw access eventually
36 */
37
38#include <fcntl.h>
39#include <sys/types.h>
40#include <sys/time.h>
41#include <sys/endian.h>
42#include <dev/wscons/wsconsio.h>
43#include <sys/ioctl.h>
44#include <errno.h>
45
46#include "mgx.h"
47
48static void MgxLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
49static void MgxSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
50static void MgxSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
51
52static void
53MgxLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
54{
55	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
56	int err, i;
57
58	pMgx->cursor.which = WSDISPLAY_CURSOR_DOALL;
59	pMgx->cursor.image = src;
60	pMgx->cursor.mask = src + pMgx->maskoffset;
61	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
62		xf86Msg(X_ERROR, "MgxLoadCursorImage: %d\n", errno);
63}
64
65void
66MgxShowCursor(ScrnInfoPtr pScrn)
67{
68	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
69
70	pMgx->cursor.which = WSDISPLAY_CURSOR_DOCUR;
71	pMgx->cursor.enable = 1;
72	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
73		xf86Msg(X_ERROR, "MgxShowCursor: %d\n", errno);
74}
75
76void
77MgxHideCursor(ScrnInfoPtr pScrn)
78{
79	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
80
81	pMgx->cursor.which = WSDISPLAY_CURSOR_DOCUR;
82	pMgx->cursor.enable = 0;
83	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
84		xf86Msg(X_ERROR, "MgxHideCursor: %d\n", errno);
85}
86
87static void
88MgxSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
89{
90	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
91	int xoff = 0, yoff = 0;
92
93	pMgx->cursor.which = WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT;
94
95	if (x < 0) {
96		xoff = -x;
97		x = 0;
98	}
99	if (y < 0) {
100		yoff = -y;
101		y = 0;
102	}
103
104	pMgx->cursor.pos.x = x;
105	pMgx->cursor.hot.x = xoff;
106	pMgx->cursor.pos.y = y;
107	pMgx->cursor.hot.y = yoff;
108
109	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
110		xf86Msg(X_ERROR, "MgxSetCursorPosition: %d\n", errno);
111}
112
113static void
114MgxSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
115{
116	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
117	u_char r[4], g[4], b[4];
118
119	pMgx->cursor.which = WSDISPLAY_CURSOR_DOCMAP;
120	pMgx->cursor.cmap.red = r;
121	pMgx->cursor.cmap.green = g;
122	pMgx->cursor.cmap.blue = b;
123	r[1] = fg & 0xff;
124	g[1] = (fg & 0xff00) >> 8;
125	b[1] = (fg & 0xff0000) >> 16;
126	r[0] = bg & 0xff;
127	g[0] = (bg & 0xff00) >> 8;
128	b[0] = (bg & 0xff0000) >> 16;
129	pMgx->cursor.cmap.index = 0;
130	pMgx->cursor.cmap.count = 2;
131	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
132		xf86Msg(X_ERROR, "MgxSetCursorColors: %d\n", errno);
133}
134
135Bool
136MgxSetupCursor(ScreenPtr pScreen)
137{
138	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
139	MgxPtr pMgx = GET_MGX_FROM_SCRN(pScrn);
140	xf86CursorInfoPtr infoPtr;
141
142	pMgx->cursor.pos.x = 0;
143	pMgx->cursor.pos.y = 0;
144	pMgx->cursor.enable = 0;
145
146	infoPtr = xf86CreateCursorInfoRec();
147	if(!infoPtr) return FALSE;
148
149	pMgx->CursorInfoRec = infoPtr;
150	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_GCURMAX, &pMgx->cursor.size) == -1) {
151		xf86Msg(X_WARNING, "No HW cursor support found\n");
152		return FALSE;
153	}
154
155	xf86Msg(X_INFO, "HW cursor enabled\n");
156
157	infoPtr->MaxWidth = pMgx->cursor.size.x;
158	infoPtr->MaxHeight = pMgx->cursor.size.y;
159	pMgx->maskoffset = ( pMgx->cursor.size.x >> 3) * pMgx->cursor.size.y;
160
161	pMgx->cursor.hot.x = 0;
162	pMgx->cursor.hot.y = 0;
163	pMgx->cursor.which = WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCUR |
164	    WSDISPLAY_CURSOR_DOPOS;
165	if(ioctl(pMgx->psdp->fd, WSDISPLAYIO_SCURSOR, &pMgx->cursor) == -1)
166		xf86Msg(X_ERROR, "WSDISPLAYIO_SCURSOR: %d\n", errno);
167
168	infoPtr->Flags = HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
169	    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
170/* XXX not sure why exactly we need this */
171#if BYTE_ORDER == BIG_ENDIAN
172	    | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
173#endif
174	;
175	infoPtr->SetCursorColors = MgxSetCursorColors;
176	infoPtr->SetCursorPosition = MgxSetCursorPosition;
177	infoPtr->LoadCursorImage = MgxLoadCursorImage;
178	infoPtr->HideCursor = MgxHideCursor;
179	infoPtr->ShowCursor = MgxShowCursor;
180	infoPtr->UseHWCursor = NULL;
181
182	return xf86InitCursor(pScreen, infoPtr);
183}
184