1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991-1997 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <stdio.h> 35 #include <sys/types.h> 36 #include <sys/ioctl.h> 37 #include <sys/signal.h> 38 #include <sys/consio.h> 39 #include <sys/fbio.h> 40 #include "vgl.h" 41 42 #define X 0xff 43 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = { 44 X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 45 X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0, 46 X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0, 47 X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0, 48 X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0, 49 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, 50 X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0, 51 X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0, 52 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, 53 0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0, 54 0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0, 55 0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0, 56 0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0, 57 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 58 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 59 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 60 }; 61 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = { 62 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 63 0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 64 0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0, 65 0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0, 66 0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0, 67 0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0, 68 0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, 69 0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0, 70 0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0, 71 0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0, 72 0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0, 73 0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0, 74 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 75 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 76 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 77 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 78 }; 79 #undef X 80 static VGLBitmap VGLMouseStdAndMask = 81 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask); 82 static VGLBitmap VGLMouseStdOrMask = 83 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask); 84 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask; 85 static int VGLMouseVisible = 0; 86 static int VGLMouseShown = 0; 87 static int VGLMouseXpos = 0; 88 static int VGLMouseYpos = 0; 89 static int VGLMouseButtons = 0; 90 static volatile sig_atomic_t VGLMintpending; 91 static volatile sig_atomic_t VGLMsuppressint; 92 93 #define INTOFF() (VGLMsuppressint++) 94 #define INTON() do { \ 95 if (--VGLMsuppressint == 0 && VGLMintpending) \ 96 VGLMouseAction(0); \ 97 } while (0) 98 99 void 100 VGLMousePointerShow() 101 { 102 byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4]; 103 VGLBitmap buffer = 104 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf); 105 byte crtcidx, crtcval, gdcidx, gdcval; 106 int i, pos, pos1; 107 108 if (!VGLMouseVisible) { 109 INTOFF(); 110 VGLMouseVisible = 1; 111 if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) { 112 crtcidx = inb(0x3c4); 113 crtcval = inb(0x3c5); 114 gdcidx = inb(0x3ce); 115 gdcval = inb(0x3cf); 116 } 117 buffer.PixelBytes = VGLDisplay->PixelBytes; 118 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, 119 &buffer, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); 120 for (pos = 0; pos < MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++) 121 for (i = 0; i < VGLDisplay->PixelBytes; i++) { 122 pos1 = pos * VGLDisplay->PixelBytes + i; 123 buffer.Bitmap[pos1] = (buffer.Bitmap[pos1] & 124 ~VGLMouseAndMask->Bitmap[pos]) | 125 VGLMouseOrMask->Bitmap[pos]; 126 } 127 __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay, 128 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); 129 if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) { 130 outb(0x3c4, crtcidx); 131 outb(0x3c5, crtcval); 132 outb(0x3ce, gdcidx); 133 outb(0x3cf, gdcval); 134 } 135 INTON(); 136 } 137 } 138 139 void 140 VGLMousePointerHide() 141 { 142 byte crtcidx, crtcval, gdcidx, gdcval; 143 144 if (VGLMouseVisible) { 145 INTOFF(); 146 VGLMouseVisible = 0; 147 if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) { 148 crtcidx = inb(0x3c4); 149 crtcval = inb(0x3c5); 150 gdcidx = inb(0x3ce); 151 gdcval = inb(0x3cf); 152 } 153 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 154 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); 155 if (VGLModeInfo.vi_mem_model != V_INFO_MM_DIRECT) { 156 outb(0x3c4, crtcidx); 157 outb(0x3c5, crtcval); 158 outb(0x3ce, gdcidx); 159 outb(0x3cf, gdcval); 160 } 161 INTON(); 162 } 163 } 164 165 void 166 VGLMouseMode(int mode) 167 { 168 if (mode == VGL_MOUSESHOW) { 169 if (VGLMouseShown == VGL_MOUSEHIDE) { 170 VGLMousePointerShow(); 171 VGLMouseShown = VGL_MOUSESHOW; 172 } 173 } 174 else { 175 if (VGLMouseShown == VGL_MOUSESHOW) { 176 VGLMousePointerHide(); 177 VGLMouseShown = VGL_MOUSEHIDE; 178 } 179 } 180 } 181 182 void 183 VGLMouseAction(int dummy) 184 { 185 struct mouse_info mouseinfo; 186 187 if (VGLMsuppressint) { 188 VGLMintpending = 1; 189 return; 190 } 191 again: 192 INTOFF(); 193 VGLMintpending = 0; 194 mouseinfo.operation = MOUSE_GETINFO; 195 ioctl(0, CONS_MOUSECTL, &mouseinfo); 196 if (VGLMouseShown == VGL_MOUSESHOW) 197 VGLMousePointerHide(); 198 VGLMouseXpos = mouseinfo.u.data.x; 199 VGLMouseYpos = mouseinfo.u.data.y; 200 VGLMouseButtons = mouseinfo.u.data.buttons; 201 if (VGLMouseShown == VGL_MOUSESHOW) 202 VGLMousePointerShow(); 203 204 /* 205 * Loop to handle any new (suppressed) signals. This is INTON() without 206 * recursion. !SA_RESTART prevents recursion in signal handling. So the 207 * maximum recursion is 2 levels. 208 */ 209 VGLMsuppressint = 0; 210 if (VGLMintpending) 211 goto again; 212 } 213 214 void 215 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask) 216 { 217 if (VGLMouseShown == VGL_MOUSESHOW) 218 VGLMousePointerHide(); 219 VGLMouseAndMask = AndMask; 220 VGLMouseOrMask = OrMask; 221 if (VGLMouseShown == VGL_MOUSESHOW) 222 VGLMousePointerShow(); 223 } 224 225 void 226 VGLMouseSetStdImage() 227 { 228 if (VGLMouseShown == VGL_MOUSESHOW) 229 VGLMousePointerHide(); 230 VGLMouseAndMask = &VGLMouseStdAndMask; 231 VGLMouseOrMask = &VGLMouseStdOrMask; 232 if (VGLMouseShown == VGL_MOUSESHOW) 233 VGLMousePointerShow(); 234 } 235 236 int 237 VGLMouseInit(int mode) 238 { 239 struct mouse_info mouseinfo; 240 int error, i, mask; 241 242 switch (VGLModeInfo.vi_mem_model) { 243 case V_INFO_MM_PACKED: 244 case V_INFO_MM_PLANAR: 245 mask = 0x0f; 246 break; 247 case V_INFO_MM_VGAX: 248 mask = 0x3f; 249 break; 250 default: 251 mask = 0xff; 252 break; 253 } 254 for (i = 0; i < 256; i++) 255 VGLMouseStdOrMask.Bitmap[i] &= mask; 256 VGLMouseSetStdImage(); 257 mouseinfo.operation = MOUSE_MODE; 258 mouseinfo.u.mode.signal = SIGUSR2; 259 if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo))) 260 return error; 261 signal(SIGUSR2, VGLMouseAction); 262 mouseinfo.operation = MOUSE_GETINFO; 263 ioctl(0, CONS_MOUSECTL, &mouseinfo); 264 VGLMouseXpos = mouseinfo.u.data.x; 265 VGLMouseYpos = mouseinfo.u.data.y; 266 VGLMouseButtons = mouseinfo.u.data.buttons; 267 VGLMouseMode(mode); 268 return 0; 269 } 270 271 void 272 VGLMouseRestore(void) 273 { 274 struct mouse_info mouseinfo; 275 276 INTOFF(); 277 mouseinfo.operation = MOUSE_GETINFO; 278 if (ioctl(0, CONS_MOUSECTL, &mouseinfo) == 0) { 279 mouseinfo.operation = MOUSE_MOVEABS; 280 mouseinfo.u.data.x = VGLMouseXpos; 281 mouseinfo.u.data.y = VGLMouseYpos; 282 ioctl(0, CONS_MOUSECTL, &mouseinfo); 283 } 284 INTON(); 285 } 286 287 int 288 VGLMouseStatus(int *x, int *y, char *buttons) 289 { 290 INTOFF(); 291 *x = VGLMouseXpos; 292 *y = VGLMouseYpos; 293 *buttons = VGLMouseButtons; 294 INTON(); 295 return VGLMouseShown; 296 } 297 298 int 299 VGLMouseFreeze(int x, int y, int width, int hight, u_long color) 300 { 301 INTOFF(); 302 if (width > 1 || hight > 1 || (color & 0xc0000000) == 0) { /* bitmap */ 303 if (VGLMouseShown == 1) { 304 int overlap; 305 306 if (x > VGLMouseXpos) 307 overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x; 308 else 309 overlap = (x + width) - VGLMouseXpos; 310 if (overlap > 0) { 311 if (y > VGLMouseYpos) 312 overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y; 313 else 314 overlap = (y + hight) - VGLMouseYpos; 315 if (overlap > 0) 316 VGLMousePointerHide(); 317 } 318 } 319 } 320 else { /* bit */ 321 if (VGLMouseShown && 322 x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE && 323 y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) { 324 if (color & 0x80000000) { /* Set */ 325 if (VGLMouseAndMask->Bitmap 326 [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) { 327 return 1; 328 } 329 } 330 } 331 } 332 return 0; 333 } 334 335 void 336 VGLMouseUnFreeze() 337 { 338 if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible && !VGLMintpending) 339 VGLMousePointerShow(); 340 while (VGLMsuppressint) 341 INTON(); 342 } 343