1 /*- 2 * Copyright (c) 1991-1997 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <signal.h> 33 #include <sys/fbio.h> 34 #include "vgl.h" 35 36 static byte VGLSavePaletteRed[256]; 37 static byte VGLSavePaletteGreen[256]; 38 static byte VGLSavePaletteBlue[256]; 39 40 #define ABS(a) (((a)<0) ? -(a) : (a)) 41 #define SGN(a) (((a)<0) ? -1 : 1) 42 #define min(x, y) (((x) < (y)) ? (x) : (y)) 43 #define max(x, y) (((x) > (y)) ? (x) : (y)) 44 45 static void 46 color2mem(u_long color, byte *b, int len) 47 { 48 switch (len) { 49 case 4: 50 b[3] = (color >> 24) & 0xff; 51 /* fallthrough */ 52 case 3: 53 b[2] = (color >> 16) & 0xff; 54 /* fallthrough */ 55 case 2: 56 b[1] = (color >> 8) & 0xff; 57 /* fallthrough */ 58 case 1: 59 default: 60 b[0] = color & 0xff; 61 break; 62 } 63 64 return; 65 } 66 67 static u_long 68 mem2color(byte *b, int len) 69 { 70 u_long color = 0; 71 72 switch (len) { 73 case 4: 74 color |= (b[3] & 0xff) << 24; 75 /* fallthrough */ 76 case 3: 77 color |= (b[2] & 0xff) << 16; 78 /* fallthrough */ 79 case 2: 80 color |= (b[1] & 0xff) << 8; 81 /* fallthrough */ 82 case 1: 83 default: 84 color |= (b[0] & 0xff); 85 break; 86 } 87 88 return color; 89 } 90 91 void 92 VGLSetXY(VGLBitmap *object, int x, int y, u_long color) 93 { 94 int offset; 95 byte b[4]; 96 97 VGLCheckSwitch(); 98 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) { 99 if (!VGLMouseFreeze(x, y, 1, 1, color)) { 100 switch (object->Type) { 101 case MEMBUF: 102 case VIDBUF8: 103 object->Bitmap[y*object->VXsize+x]=((byte)color); 104 break; 105 case VIDBUF8S: 106 object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=((byte)color); 107 break; 108 case VIDBUF16: 109 case VIDBUF24: 110 case VIDBUF32: 111 color2mem(color, b, object->PixelBytes); 112 bcopy(b, &object->Bitmap[(y*object->VXsize+x) * object->PixelBytes], 113 object->PixelBytes); 114 break; 115 case VIDBUF16S: 116 case VIDBUF24S: 117 case VIDBUF32S: 118 color2mem(color, b, object->PixelBytes); 119 offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes); 120 bcopy(b, &object->Bitmap[offset], object->PixelBytes); 121 break; 122 case VIDBUF8X: 123 outb(0x3c4, 0x02); 124 outb(0x3c5, 0x01 << (x&0x3)); 125 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color); 126 break; 127 case VIDBUF4S: 128 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 129 goto set_planar; 130 case VIDBUF4: 131 offset = y*VGLAdpInfo.va_line_width + x/8; 132 set_planar: 133 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 134 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */ 135 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */ 136 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */ 137 object->Bitmap[offset] |= (byte)color; 138 } 139 } 140 VGLMouseUnFreeze(); 141 } 142 } 143 144 u_long 145 VGLGetXY(VGLBitmap *object, int x, int y) 146 { 147 int offset; 148 byte b[4]; 149 #if 0 150 int i; 151 u_long color; 152 byte mask; 153 #endif 154 155 VGLCheckSwitch(); 156 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize) 157 return 0; 158 switch (object->Type) { 159 case MEMBUF: 160 case VIDBUF8: 161 return object->Bitmap[((y*object->VXsize)+x)]; 162 case VIDBUF8S: 163 return object->Bitmap[VGLSetSegment(y*object->VXsize+x)]; 164 case VIDBUF16: 165 case VIDBUF24: 166 case VIDBUF32: 167 bcopy(&object->Bitmap[(y*object->VXsize+x) * object->PixelBytes], 168 b, object->PixelBytes); 169 return (mem2color(b, object->PixelBytes)); 170 case VIDBUF16S: 171 case VIDBUF24S: 172 case VIDBUF32S: 173 offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes); 174 bcopy(&object->Bitmap[offset], b, object->PixelBytes); 175 176 return (mem2color(b, object->PixelBytes)); 177 case VIDBUF8X: 178 outb(0x3ce, 0x04); outb(0x3cf, x & 0x3); 179 return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)]; 180 case VIDBUF4S: 181 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 182 goto get_planar; 183 case VIDBUF4: 184 offset = y*VGLAdpInfo.va_line_width + x/8; 185 get_planar: 186 #if 1 187 return (object->Bitmap[offset]&(0x80>>(x%8))) ? 1 : 0; /* XXX */ 188 #else 189 color = 0; 190 mask = 0x80 >> (x%8); 191 for (i = 0; i < VGLModeInfo.vi_planes; i++) { 192 outb(0x3ce, 0x04); outb(0x3cf, i); 193 color |= (object->Bitmap[offset] & mask) ? (1 << i) : 0; 194 } 195 return color; 196 #endif 197 } 198 return 0; /* XXX black? */ 199 } 200 201 void 202 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 203 { 204 int d, x, y, ax, ay, sx, sy, dx, dy; 205 206 dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); x = x1; 207 dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); y = y1; 208 209 if (ax>ay) { /* x dominant */ 210 d = ay-(ax>>1); 211 for (;;) { 212 VGLSetXY(object, x, y, color); 213 if (x==x2) 214 break; 215 if (d>=0) { 216 y += sy; d -= ax; 217 } 218 x += sx; d += ay; 219 } 220 } 221 else { /* y dominant */ 222 d = ax-(ay>>1); 223 for (;;) { 224 VGLSetXY(object, x, y, color); 225 if (y==y2) 226 break; 227 if (d>=0) { 228 x += sx; d -= ay; 229 } 230 y += sy; d += ax; 231 } 232 } 233 } 234 235 void 236 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 237 { 238 VGLLine(object, x1, y1, x2, y1, color); 239 VGLLine(object, x2, y1, x2, y2, color); 240 VGLLine(object, x2, y2, x1, y2, color); 241 VGLLine(object, x1, y2, x1, y1, color); 242 } 243 244 void 245 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color) 246 { 247 int y; 248 249 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color); 250 } 251 252 void 253 inline set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 254 { 255 if (x!=0) { 256 VGLSetXY(object, xc+x, yc+y, color); 257 VGLSetXY(object, xc-x, yc+y, color); 258 if (y!=0) { 259 VGLSetXY(object, xc+x, yc-y, color); 260 VGLSetXY(object, xc-x, yc-y, color); 261 } 262 } 263 else { 264 VGLSetXY(object, xc, yc+y, color); 265 if (y!=0) 266 VGLSetXY(object, xc, yc-y, color); 267 } 268 } 269 270 void 271 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 272 { 273 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 274 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 275 276 while (dx<dy) { 277 set4pixels(object, x, y, xc, yc, color); 278 if (d>0) { 279 y--; dy-=asq2; d-=dy; 280 } 281 x++; dx+=bsq2; d+=bsq+dx; 282 } 283 d+=(3*(asq-bsq)/2-(dx+dy))/2; 284 while (y>=0) { 285 set4pixels(object, x, y, xc, yc, color); 286 if (d<0) { 287 x++; dx+=bsq2; d+=dx; 288 } 289 y--; dy-=asq2; d+=asq-dy; 290 } 291 } 292 293 void 294 inline set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color) 295 { 296 if (x!=0) { 297 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color); 298 if (y!=0) 299 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color); 300 } 301 else { 302 VGLLine(object, xc, yc+y, xc, yc-y, color); 303 } 304 } 305 306 void 307 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color) 308 { 309 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 310 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 311 312 while (dx<dy) { 313 set2lines(object, x, y, xc, yc, color); 314 if (d>0) { 315 y--; dy-=asq2; d-=dy; 316 } 317 x++; dx+=bsq2; d+=bsq+dx; 318 } 319 d+=(3*(asq-bsq)/2-(dx+dy))/2; 320 while (y>=0) { 321 set2lines(object, x, y, xc, yc, color); 322 if (d<0) { 323 x++; dx+=bsq2; d+=dx; 324 } 325 y--; dy-=asq2; d+=asq-dy; 326 } 327 } 328 329 void 330 VGLClear(VGLBitmap *object, u_long color) 331 { 332 int offset; 333 int len; 334 int i, total = 0; 335 byte b[4]; 336 337 VGLCheckSwitch(); 338 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color); /* XXX */ 339 switch (object->Type) { 340 case MEMBUF: 341 case VIDBUF8: 342 memset(object->Bitmap, (byte)color, object->VXsize*object->VYsize); 343 break; 344 345 case VIDBUF8S: 346 for (offset = 0; offset < object->VXsize*object->VYsize; ) { 347 VGLSetSegment(offset); 348 len = min(object->VXsize*object->VYsize - offset, 349 VGLAdpInfo.va_window_size); 350 memset(object->Bitmap, (byte)color, len); 351 offset += len; 352 } 353 break; 354 case VIDBUF16: 355 case VIDBUF24: 356 case VIDBUF32: 357 color2mem(color, b, object->PixelBytes); 358 total = object->VXsize*object->VYsize*object->PixelBytes; 359 for (i = 0; i < total; i += object->PixelBytes) 360 bcopy(b, object->Bitmap + i, object->PixelBytes); 361 break; 362 363 case VIDBUF16S: 364 case VIDBUF24S: 365 case VIDBUF32S: 366 color2mem(color, b, object->PixelBytes); 367 total = object->VXsize*object->VYsize*object->PixelBytes; 368 for (offset = 0; offset < total; ) { 369 VGLSetSegment(offset); 370 len = min(total - offset, VGLAdpInfo.va_window_size); 371 for (i = 0; i < len; i += object->PixelBytes) 372 bcopy(b, object->Bitmap + offset + i, object->PixelBytes); 373 offset += len; 374 } 375 break; 376 377 case VIDBUF8X: 378 /* XXX works only for Xsize % 4 = 0 */ 379 outb(0x3c6, 0xff); 380 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 381 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize); 382 break; 383 384 case VIDBUF4: 385 case VIDBUF4S: 386 /* XXX works only for Xsize % 8 = 0 */ 387 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 388 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */ 389 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 390 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 391 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) { 392 VGLSetSegment(offset); 393 len = min(object->VXsize*object->VYsize - offset, 394 VGLAdpInfo.va_window_size); 395 memset(object->Bitmap, (byte)color, len); 396 offset += len; 397 } 398 outb(0x3ce, 0x05); outb(0x3cf, 0x00); 399 break; 400 } 401 VGLMouseUnFreeze(); 402 } 403 404 void 405 VGLRestorePalette() 406 { 407 int i; 408 409 outb(0x3C6, 0xFF); 410 inb(0x3DA); 411 outb(0x3C8, 0x00); 412 for (i=0; i<256; i++) { 413 outb(0x3C9, VGLSavePaletteRed[i]); 414 inb(0x84); 415 outb(0x3C9, VGLSavePaletteGreen[i]); 416 inb(0x84); 417 outb(0x3C9, VGLSavePaletteBlue[i]); 418 inb(0x84); 419 } 420 inb(0x3DA); 421 outb(0x3C0, 0x20); 422 } 423 424 void 425 VGLSavePalette() 426 { 427 int i; 428 429 outb(0x3C6, 0xFF); 430 inb(0x3DA); 431 outb(0x3C7, 0x00); 432 for (i=0; i<256; i++) { 433 VGLSavePaletteRed[i] = inb(0x3C9); 434 inb(0x84); 435 VGLSavePaletteGreen[i] = inb(0x3C9); 436 inb(0x84); 437 VGLSavePaletteBlue[i] = inb(0x3C9); 438 inb(0x84); 439 } 440 inb(0x3DA); 441 outb(0x3C0, 0x20); 442 } 443 444 void 445 VGLSetPalette(byte *red, byte *green, byte *blue) 446 { 447 int i; 448 449 for (i=0; i<256; i++) { 450 VGLSavePaletteRed[i] = red[i]; 451 VGLSavePaletteGreen[i] = green[i]; 452 VGLSavePaletteBlue[i] = blue[i]; 453 } 454 VGLCheckSwitch(); 455 outb(0x3C6, 0xFF); 456 inb(0x3DA); 457 outb(0x3C8, 0x00); 458 for (i=0; i<256; i++) { 459 outb(0x3C9, VGLSavePaletteRed[i]); 460 inb(0x84); 461 outb(0x3C9, VGLSavePaletteGreen[i]); 462 inb(0x84); 463 outb(0x3C9, VGLSavePaletteBlue[i]); 464 inb(0x84); 465 } 466 inb(0x3DA); 467 outb(0x3C0, 0x20); 468 } 469 470 void 471 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue) 472 { 473 VGLSavePaletteRed[color] = red; 474 VGLSavePaletteGreen[color] = green; 475 VGLSavePaletteBlue[color] = blue; 476 VGLCheckSwitch(); 477 outb(0x3C6, 0xFF); 478 inb(0x3DA); 479 outb(0x3C8, color); 480 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue); 481 inb(0x3DA); 482 outb(0x3C0, 0x20); 483 } 484 485 void 486 VGLSetBorder(byte color) 487 { 488 VGLCheckSwitch(); 489 inb(0x3DA); 490 outb(0x3C0,0x11); outb(0x3C0, color); 491 inb(0x3DA); 492 outb(0x3C0, 0x20); 493 } 494 495 void 496 VGLBlankDisplay(int blank) 497 { 498 byte val; 499 500 VGLCheckSwitch(); 501 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01); 502 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF))); 503 } 504