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 without 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 * $FreeBSD: src/lib/libvgl/simple.c,v 1.4 1999/11/08 11:37:39 yokota Exp $ 29 * $DragonFly: src/lib/libvgl/simple.c,v 1.3 2008/09/30 16:57:06 swildner Exp $ 30 */ 31 32 #include <signal.h> 33 #include <machine/console.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 void 46 VGLSetXY(VGLBitmap *object, int x, int y, byte color) 47 { 48 int offset; 49 50 VGLCheckSwitch(); 51 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) { 52 if (!VGLMouseFreeze(x, y, 1, 1, color)) { 53 switch (object->Type) { 54 case MEMBUF: 55 case VIDBUF8: 56 object->Bitmap[y*object->VXsize+x]=(color); 57 break; 58 case VIDBUF8S: 59 object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=(color); 60 break; 61 case VIDBUF8X: 62 outb(0x3c4, 0x02); 63 outb(0x3c5, 0x01 << (x&0x3)); 64 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = (color); 65 break; 66 case VIDBUF4S: 67 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 68 goto set_planar; 69 case VIDBUF4: 70 offset = y*VGLAdpInfo.va_line_width + x/8; 71 set_planar: 72 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 73 outb(0x3ce, 0x00); outb(0x3cf, color & 0x0f); /* set/reset */ 74 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */ 75 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */ 76 object->Bitmap[offset] |= color; 77 } 78 } 79 VGLMouseUnFreeze(); 80 } 81 } 82 83 byte 84 VGLGetXY(VGLBitmap *object, int x, int y) 85 { 86 int offset; 87 #if 0 88 int i; 89 byte color; 90 byte mask; 91 #endif 92 93 VGLCheckSwitch(); 94 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize) 95 return 0; 96 switch (object->Type) { 97 case MEMBUF: 98 case VIDBUF8: 99 return object->Bitmap[((y*object->VXsize)+x)]; 100 case VIDBUF8S: 101 return object->Bitmap[VGLSetSegment(y*object->VXsize+x)]; 102 case VIDBUF8X: 103 outb(0x3ce, 0x04); outb(0x3cf, x & 0x3); 104 return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)]; 105 case VIDBUF4S: 106 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8); 107 goto get_planar; 108 case VIDBUF4: 109 offset = y*VGLAdpInfo.va_line_width + x/8; 110 get_planar: 111 #if 1 112 return (object->Bitmap[offset]&(0x80>>(x%8))) ? 1 : 0; /* XXX */ 113 #else 114 color = 0; 115 mask = 0x80 >> (x%8); 116 for (i = 0; i < VGLModeInfo.vi_planes; i++) { 117 outb(0x3ce, 0x04); outb(0x3cf, i); 118 color |= (object->Bitmap[offset] & mask) ? (1 << i) : 0; 119 } 120 return color; 121 #endif 122 } 123 return 0; 124 } 125 126 void 127 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color) 128 { 129 int d, x, y, ax, ay, sx, sy, dx, dy; 130 131 dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); x = x1; 132 dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); y = y1; 133 134 if (ax>ay) { /* x dominant */ 135 d = ay-(ax>>1); 136 for (;;) { 137 VGLSetXY(object, x, y, color); 138 if (x==x2) 139 break; 140 if (d>=0) { 141 y += sy; d -= ax; 142 } 143 x += sx; d += ay; 144 } 145 } 146 else { /* y dominant */ 147 d = ax-(ay>>1); 148 for (;;) { 149 VGLSetXY(object, x, y, color); 150 if (y==y2) 151 break; 152 if (d>=0) { 153 x += sx; d -= ay; 154 } 155 y += sy; d += ax; 156 } 157 } 158 } 159 160 void 161 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color) 162 { 163 VGLLine(object, x1, y1, x2, y1, color); 164 VGLLine(object, x2, y1, x2, y2, color); 165 VGLLine(object, x2, y2, x1, y2, color); 166 VGLLine(object, x1, y2, x1, y1, color); 167 } 168 169 void 170 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color) 171 { 172 int y; 173 174 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color); 175 } 176 177 void 178 inline set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, byte color) 179 { 180 if (x!=0) { 181 VGLSetXY(object, xc+x, yc+y, color); 182 VGLSetXY(object, xc-x, yc+y, color); 183 if (y!=0) { 184 VGLSetXY(object, xc+x, yc-y, color); 185 VGLSetXY(object, xc-x, yc-y, color); 186 } 187 } 188 else { 189 VGLSetXY(object, xc, yc+y, color); 190 if (y!=0) 191 VGLSetXY(object, xc, yc-y, color); 192 } 193 } 194 195 void 196 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, byte color) 197 { 198 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 199 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 200 201 while (dx<dy) { 202 set4pixels(object, x, y, xc, yc, color); 203 if (d>0) { 204 y--; dy-=asq2; d-=dy; 205 } 206 x++; dx+=bsq2; d+=bsq+dx; 207 } 208 d+=(3*(asq-bsq)/2-(dx+dy))/2; 209 while (y>=0) { 210 set4pixels(object, x, y, xc, yc, color); 211 if (d<0) { 212 x++; dx+=bsq2; d+=dx; 213 } 214 y--; dy-=asq2; d+=asq-dy; 215 } 216 } 217 218 void 219 inline set2lines(VGLBitmap *object, int x, int y, int xc, int yc, byte color) 220 { 221 if (x!=0) { 222 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color); 223 if (y!=0) 224 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color); 225 } 226 else { 227 VGLLine(object, xc, yc+y, xc, yc-y, color); 228 } 229 } 230 231 void 232 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, byte color) 233 { 234 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b; 235 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b; 236 237 while (dx<dy) { 238 set2lines(object, x, y, xc, yc, color); 239 if (d>0) { 240 y--; dy-=asq2; d-=dy; 241 } 242 x++; dx+=bsq2; d+=bsq+dx; 243 } 244 d+=(3*(asq-bsq)/2-(dx+dy))/2; 245 while (y>=0) { 246 set2lines(object, x, y, xc, yc, color); 247 if (d<0) { 248 x++; dx+=bsq2; d+=dx; 249 } 250 y--; dy-=asq2; d+=asq-dy; 251 } 252 } 253 254 void 255 VGLClear(VGLBitmap *object, byte color) 256 { 257 int offset; 258 int len; 259 260 VGLCheckSwitch(); 261 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color); 262 switch (object->Type) { 263 case MEMBUF: 264 case VIDBUF8: 265 memset(object->Bitmap, color, object->VXsize*object->VYsize); 266 break; 267 268 case VIDBUF8S: 269 for (offset = 0; offset < object->VXsize*object->VYsize; ) { 270 VGLSetSegment(offset); 271 len = min(object->VXsize*object->VYsize - offset, 272 VGLAdpInfo.va_window_size); 273 memset(object->Bitmap, color, len); 274 offset += len; 275 } 276 break; 277 278 case VIDBUF8X: 279 /* XXX works only for Xsize % 4 = 0 */ 280 outb(0x3c6, 0xff); 281 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 282 memset(object->Bitmap, color, VGLAdpInfo.va_line_width*object->VYsize); 283 break; 284 285 case VIDBUF4: 286 case VIDBUF4S: 287 /* XXX works only for Xsize % 8 = 0 */ 288 outb(0x3c4, 0x02); outb(0x3c5, 0x0f); 289 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */ 290 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 291 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 292 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) { 293 VGLSetSegment(offset); 294 len = min(object->VXsize*object->VYsize - offset, 295 VGLAdpInfo.va_window_size); 296 memset(object->Bitmap, color, len); 297 offset += len; 298 } 299 outb(0x3ce, 0x05); outb(0x3cf, 0x00); 300 break; 301 } 302 VGLMouseUnFreeze(); 303 } 304 305 void 306 VGLRestorePalette(void) 307 { 308 int i; 309 310 outb(0x3C6, 0xFF); 311 inb(0x3DA); 312 outb(0x3C8, 0x00); 313 for (i=0; i<256; i++) { 314 outb(0x3C9, VGLSavePaletteRed[i]); 315 inb(0x84); 316 outb(0x3C9, VGLSavePaletteGreen[i]); 317 inb(0x84); 318 outb(0x3C9, VGLSavePaletteBlue[i]); 319 inb(0x84); 320 } 321 inb(0x3DA); 322 outb(0x3C0, 0x20); 323 } 324 325 void 326 VGLSavePalette(void) 327 { 328 int i; 329 330 outb(0x3C6, 0xFF); 331 inb(0x3DA); 332 outb(0x3C7, 0x00); 333 for (i=0; i<256; i++) { 334 VGLSavePaletteRed[i] = inb(0x3C9); 335 inb(0x84); 336 VGLSavePaletteGreen[i] = inb(0x3C9); 337 inb(0x84); 338 VGLSavePaletteBlue[i] = inb(0x3C9); 339 inb(0x84); 340 } 341 inb(0x3DA); 342 outb(0x3C0, 0x20); 343 } 344 345 void 346 VGLSetPalette(byte *red, byte *green, byte *blue) 347 { 348 int i; 349 350 for (i=0; i<256; i++) { 351 VGLSavePaletteRed[i] = red[i]; 352 VGLSavePaletteGreen[i] = green[i]; 353 VGLSavePaletteBlue[i] = blue[i]; 354 } 355 VGLCheckSwitch(); 356 outb(0x3C6, 0xFF); 357 inb(0x3DA); 358 outb(0x3C8, 0x00); 359 for (i=0; i<256; i++) { 360 outb(0x3C9, VGLSavePaletteRed[i]); 361 inb(0x84); 362 outb(0x3C9, VGLSavePaletteGreen[i]); 363 inb(0x84); 364 outb(0x3C9, VGLSavePaletteBlue[i]); 365 inb(0x84); 366 } 367 inb(0x3DA); 368 outb(0x3C0, 0x20); 369 } 370 371 void 372 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue) 373 { 374 VGLSavePaletteRed[color] = red; 375 VGLSavePaletteGreen[color] = green; 376 VGLSavePaletteBlue[color] = blue; 377 VGLCheckSwitch(); 378 outb(0x3C6, 0xFF); 379 inb(0x3DA); 380 outb(0x3C8, color); 381 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue); 382 inb(0x3DA); 383 outb(0x3C0, 0x20); 384 } 385 386 void 387 VGLSetBorder(byte color) 388 { 389 VGLCheckSwitch(); 390 inb(0x3DA); 391 outb(0x3C0,0x11); outb(0x3C0, color); 392 inb(0x3DA); 393 outb(0x3C0, 0x20); 394 } 395 396 void 397 VGLBlankDisplay(int blank) 398 { 399 byte val; 400 401 VGLCheckSwitch(); 402 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01); 403 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF))); 404 } 405