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 <signal.h>
35 #include <sys/fbio.h>
36 #include <sys/kbio.h>
37 #include <sys/endian.h>
38 #include "vgl.h"
39
40 static int VGLBlank;
41 static byte VGLBorderColor;
42 static byte VGLSavePaletteRed[256];
43 static byte VGLSavePaletteGreen[256];
44 static byte VGLSavePaletteBlue[256];
45
46 #define ABS(a) (((a)<0) ? -(a) : (a))
47 #define SGN(a) (((a)<0) ? -1 : 1)
48 #define min(x, y) (((x) < (y)) ? (x) : (y))
49 #define max(x, y) (((x) > (y)) ? (x) : (y))
50
51 void
VGLSetXY(VGLBitmap * object,int x,int y,u_long color)52 VGLSetXY(VGLBitmap *object, int x, int y, u_long color)
53 {
54 int offset, soffset, undermouse;
55
56 VGLCheckSwitch();
57 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) {
58 if (object == VGLDisplay) {
59 undermouse = VGLMouseFreezeXY(x, y);
60 VGLSetXY(&VGLVDisplay, x, y, color);
61 } else if (object->Type != MEMBUF)
62 return; /* invalid */
63 else
64 undermouse = 0;
65 if (!undermouse) {
66 offset = (y * object->VXsize + x) * object->PixelBytes;
67 switch (object->Type) {
68 case VIDBUF8S:
69 case VIDBUF16S:
70 case VIDBUF32S:
71 offset = VGLSetSegment(offset);
72 /* FALLTHROUGH */
73 case MEMBUF:
74 case VIDBUF8:
75 case VIDBUF16:
76 case VIDBUF24:
77 case VIDBUF32:
78 color = htole32(color);
79 switch (object->PixelBytes) {
80 case 1:
81 memcpy(&object->Bitmap[offset], &color, 1);
82 break;
83 case 2:
84 memcpy(&object->Bitmap[offset], &color, 2);
85 break;
86 case 3:
87 memcpy(&object->Bitmap[offset], &color, 3);
88 break;
89 case 4:
90 memcpy(&object->Bitmap[offset], &color, 4);
91 break;
92 }
93 break;
94 case VIDBUF24S:
95 soffset = VGLSetSegment(offset);
96 color = htole32(color);
97 switch (VGLAdpInfo.va_window_size - soffset) {
98 case 1:
99 memcpy(&object->Bitmap[soffset], &color, 1);
100 soffset = VGLSetSegment(offset + 1);
101 memcpy(&object->Bitmap[soffset], (byte *)&color + 1, 2);
102 break;
103 case 2:
104 memcpy(&object->Bitmap[soffset], &color, 2);
105 soffset = VGLSetSegment(offset + 2);
106 memcpy(&object->Bitmap[soffset], (byte *)&color + 2, 1);
107 break;
108 default:
109 memcpy(&object->Bitmap[soffset], &color, 3);
110 break;
111 }
112 break;
113 case VIDBUF8X:
114 outb(0x3c4, 0x02);
115 outb(0x3c5, 0x01 << (x&0x3));
116 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color);
117 break;
118 case VIDBUF4S:
119 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8);
120 goto set_planar;
121 case VIDBUF4:
122 offset = y*VGLAdpInfo.va_line_width + x/8;
123 set_planar:
124 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
125 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */
126 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */
127 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */
128 object->Bitmap[offset] |= (byte)color;
129 }
130 }
131 if (object == VGLDisplay)
132 VGLMouseUnFreeze();
133 }
134 }
135
136 u_long
VGLGetXY(VGLBitmap * object,int x,int y)137 VGLGetXY(VGLBitmap *object, int x, int y)
138 {
139 u_long color;
140 int offset;
141
142 VGLCheckSwitch();
143 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize)
144 return 0;
145 if (object == VGLDisplay)
146 object = &VGLVDisplay;
147 else if (object->Type != MEMBUF)
148 return 0; /* invalid */
149 offset = (y * object->VXsize + x) * object->PixelBytes;
150 switch (object->PixelBytes) {
151 case 1:
152 memcpy(&color, &object->Bitmap[offset], 1);
153 return le32toh(color) & 0xff;
154 case 2:
155 memcpy(&color, &object->Bitmap[offset], 2);
156 return le32toh(color) & 0xffff;
157 case 3:
158 memcpy(&color, &object->Bitmap[offset], 3);
159 return le32toh(color) & 0xffffff;
160 case 4:
161 memcpy(&color, &object->Bitmap[offset], 4);
162 return le32toh(color);
163 }
164 return 0; /* invalid */
165 }
166
167 /*
168 * Symmetric Double Step Line Algorithm by Brian Wyvill from
169 * "Graphics Gems", Academic Press, 1990.
170 */
171
172 #define SL_SWAP(a,b) {a^=b; b^=a; a^=b;}
173 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
174
175 void
plot(VGLBitmap * object,int x,int y,int flag,u_long color)176 plot(VGLBitmap * object, int x, int y, int flag, u_long color)
177 {
178 /* non-zero flag indicates the pixels need swapping back. */
179 if (flag)
180 VGLSetXY(object, y, x, color);
181 else
182 VGLSetXY(object, x, y, color);
183 }
184
185
186 void
VGLLine(VGLBitmap * object,int x1,int y1,int x2,int y2,u_long color)187 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
188 {
189 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
190 int sign_x, sign_y, step, reverse, i;
191
192 dx = SL_ABSOLUTE(x2, x1, sign_x);
193 dy = SL_ABSOLUTE(y2, y1, sign_y);
194 /* decide increment sign by the slope sign */
195 if (sign_x == sign_y)
196 step = 1;
197 else
198 step = -1;
199
200 if (dy > dx) { /* chooses axis of greatest movement (make dx) */
201 SL_SWAP(x1, y1);
202 SL_SWAP(x2, y2);
203 SL_SWAP(dx, dy);
204 reverse = 1;
205 } else
206 reverse = 0;
207 /* note error check for dx==0 should be included here */
208 if (x1 > x2) { /* start from the smaller coordinate */
209 x = x2;
210 y = y2;
211 /* x1 = x1;
212 y1 = y1; */
213 } else {
214 x = x1;
215 y = y1;
216 x1 = x2;
217 y1 = y2;
218 }
219
220
221 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
222 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
223 /* In fact (dx-1)/4 as 2 pixels are already plotted */
224 xend = (dx - 1) / 4;
225 pixels_left = (dx - 1) % 4; /* number of pixels left over at the
226 * end */
227 plot(object, x, y, reverse, color);
228 if (pixels_left < 0)
229 return; /* plot only one pixel for zero length
230 * vectors */
231 plot(object, x1, y1, reverse, color); /* plot first two points */
232 incr2 = 4 * dy - 2 * dx;
233 if (incr2 < 0) { /* slope less than 1/2 */
234 c = 2 * dy;
235 incr1 = 2 * c;
236 D = incr1 - dx;
237
238 for (i = 0; i < xend; i++) { /* plotting loop */
239 ++x;
240 --x1;
241 if (D < 0) {
242 /* pattern 1 forwards */
243 plot(object, x, y, reverse, color);
244 plot(object, ++x, y, reverse, color);
245 /* pattern 1 backwards */
246 plot(object, x1, y1, reverse, color);
247 plot(object, --x1, y1, reverse, color);
248 D += incr1;
249 } else {
250 if (D < c) {
251 /* pattern 2 forwards */
252 plot(object, x, y, reverse, color);
253 plot(object, ++x, y += step, reverse,
254 color);
255 /* pattern 2 backwards */
256 plot(object, x1, y1, reverse, color);
257 plot(object, --x1, y1 -= step, reverse,
258 color);
259 } else {
260 /* pattern 3 forwards */
261 plot(object, x, y += step, reverse, color);
262 plot(object, ++x, y, reverse, color);
263 /* pattern 3 backwards */
264 plot(object, x1, y1 -= step, reverse,
265 color);
266 plot(object, --x1, y1, reverse, color);
267 }
268 D += incr2;
269 }
270 } /* end for */
271
272 /* plot last pattern */
273 if (pixels_left) {
274 if (D < 0) {
275 plot(object, ++x, y, reverse, color); /* pattern 1 */
276 if (pixels_left > 1)
277 plot(object, ++x, y, reverse, color);
278 if (pixels_left > 2)
279 plot(object, --x1, y1, reverse, color);
280 } else {
281 if (D < c) {
282 plot(object, ++x, y, reverse, color); /* pattern 2 */
283 if (pixels_left > 1)
284 plot(object, ++x, y += step, reverse, color);
285 if (pixels_left > 2)
286 plot(object, --x1, y1, reverse, color);
287 } else {
288 /* pattern 3 */
289 plot(object, ++x, y += step, reverse, color);
290 if (pixels_left > 1)
291 plot(object, ++x, y, reverse, color);
292 if (pixels_left > 2)
293 plot(object, --x1, y1 -= step, reverse, color);
294 }
295 }
296 } /* end if pixels_left */
297 }
298 /* end slope < 1/2 */
299 else { /* slope greater than 1/2 */
300 c = 2 * (dy - dx);
301 incr1 = 2 * c;
302 D = incr1 + dx;
303 for (i = 0; i < xend; i++) {
304 ++x;
305 --x1;
306 if (D > 0) {
307 /* pattern 4 forwards */
308 plot(object, x, y += step, reverse, color);
309 plot(object, ++x, y += step, reverse, color);
310 /* pattern 4 backwards */
311 plot(object, x1, y1 -= step, reverse, color);
312 plot(object, --x1, y1 -= step, reverse, color);
313 D += incr1;
314 } else {
315 if (D < c) {
316 /* pattern 2 forwards */
317 plot(object, x, y, reverse, color);
318 plot(object, ++x, y += step, reverse,
319 color);
320
321 /* pattern 2 backwards */
322 plot(object, x1, y1, reverse, color);
323 plot(object, --x1, y1 -= step, reverse,
324 color);
325 } else {
326 /* pattern 3 forwards */
327 plot(object, x, y += step, reverse, color);
328 plot(object, ++x, y, reverse, color);
329 /* pattern 3 backwards */
330 plot(object, x1, y1 -= step, reverse, color);
331 plot(object, --x1, y1, reverse, color);
332 }
333 D += incr2;
334 }
335 } /* end for */
336 /* plot last pattern */
337 if (pixels_left) {
338 if (D > 0) {
339 plot(object, ++x, y += step, reverse, color); /* pattern 4 */
340 if (pixels_left > 1)
341 plot(object, ++x, y += step, reverse,
342 color);
343 if (pixels_left > 2)
344 plot(object, --x1, y1 -= step, reverse,
345 color);
346 } else {
347 if (D < c) {
348 plot(object, ++x, y, reverse, color); /* pattern 2 */
349 if (pixels_left > 1)
350 plot(object, ++x, y += step, reverse, color);
351 if (pixels_left > 2)
352 plot(object, --x1, y1, reverse, color);
353 } else {
354 /* pattern 3 */
355 plot(object, ++x, y += step, reverse, color);
356 if (pixels_left > 1)
357 plot(object, ++x, y, reverse, color);
358 if (pixels_left > 2) {
359 if (D > c) /* step 3 */
360 plot(object, --x1, y1 -= step, reverse, color);
361 else /* step 2 */
362 plot(object, --x1, y1, reverse, color);
363 }
364 }
365 }
366 }
367 }
368 }
369
370 void
VGLBox(VGLBitmap * object,int x1,int y1,int x2,int y2,u_long color)371 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
372 {
373 VGLLine(object, x1, y1, x2, y1, color);
374 VGLLine(object, x2, y1, x2, y2, color);
375 VGLLine(object, x2, y2, x1, y2, color);
376 VGLLine(object, x1, y2, x1, y1, color);
377 }
378
379 void
VGLFilledBox(VGLBitmap * object,int x1,int y1,int x2,int y2,u_long color)380 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
381 {
382 int y;
383
384 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color);
385 }
386
387 static inline void
set4pixels(VGLBitmap * object,int x,int y,int xc,int yc,u_long color)388 set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
389 {
390 if (x!=0) {
391 VGLSetXY(object, xc+x, yc+y, color);
392 VGLSetXY(object, xc-x, yc+y, color);
393 if (y!=0) {
394 VGLSetXY(object, xc+x, yc-y, color);
395 VGLSetXY(object, xc-x, yc-y, color);
396 }
397 }
398 else {
399 VGLSetXY(object, xc, yc+y, color);
400 if (y!=0)
401 VGLSetXY(object, xc, yc-y, color);
402 }
403 }
404
405 void
VGLEllipse(VGLBitmap * object,int xc,int yc,int a,int b,u_long color)406 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
407 {
408 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
409 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
410
411 while (dx<dy) {
412 set4pixels(object, x, y, xc, yc, color);
413 if (d>0) {
414 y--; dy-=asq2; d-=dy;
415 }
416 x++; dx+=bsq2; d+=bsq+dx;
417 }
418 d+=(3*(asq-bsq)/2-(dx+dy))/2;
419 while (y>=0) {
420 set4pixels(object, x, y, xc, yc, color);
421 if (d<0) {
422 x++; dx+=bsq2; d+=dx;
423 }
424 y--; dy-=asq2; d+=asq-dy;
425 }
426 }
427
428 static inline void
set2lines(VGLBitmap * object,int x,int y,int xc,int yc,u_long color)429 set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
430 {
431 if (x!=0) {
432 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color);
433 if (y!=0)
434 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color);
435 }
436 else {
437 VGLLine(object, xc, yc+y, xc, yc-y, color);
438 }
439 }
440
441 void
VGLFilledEllipse(VGLBitmap * object,int xc,int yc,int a,int b,u_long color)442 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
443 {
444 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
445 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
446
447 while (dx<dy) {
448 set2lines(object, x, y, xc, yc, color);
449 if (d>0) {
450 y--; dy-=asq2; d-=dy;
451 }
452 x++; dx+=bsq2; d+=bsq+dx;
453 }
454 d+=(3*(asq-bsq)/2-(dx+dy))/2;
455 while (y>=0) {
456 set2lines(object, x, y, xc, yc, color);
457 if (d<0) {
458 x++; dx+=bsq2; d+=dx;
459 }
460 y--; dy-=asq2; d+=asq-dy;
461 }
462 }
463
464 void
VGLClear(VGLBitmap * object,u_long color)465 VGLClear(VGLBitmap *object, u_long color)
466 {
467 VGLBitmap src;
468 int i, len, mousemode, offset;
469
470 VGLCheckSwitch();
471 if (object == VGLDisplay) {
472 VGLMouseFreeze();
473 VGLClear(&VGLVDisplay, color);
474 } else if (object->Type != MEMBUF)
475 return; /* invalid */
476 switch (object->Type) {
477 case MEMBUF:
478 case VIDBUF8:
479 case VIDBUF8S:
480 case VIDBUF16:
481 case VIDBUF16S:
482 case VIDBUF24:
483 case VIDBUF24S:
484 case VIDBUF32:
485 case VIDBUF32S:
486 src.Type = MEMBUF;
487 src.Xsize = object->Xsize;
488 src.VXsize = object->VXsize;
489 src.Ysize = 1;
490 src.VYsize = 1;
491 src.Xorigin = 0;
492 src.Yorigin = 0;
493 src.Bitmap = alloca(object->VXsize * object->PixelBytes);
494 src.PixelBytes = object->PixelBytes;
495 color = htole32(color);
496 for (i = 0; i < object->VXsize; i++)
497 bcopy(&color, src.Bitmap + i * object->PixelBytes, object->PixelBytes);
498 for (i = 0; i < object->VYsize; i++)
499 __VGLBitmapCopy(&src, 0, 0, object, 0, i, object->VXsize, -1);
500 break;
501
502 case VIDBUF8X:
503 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
504 /* XXX works only for Xsize % 4 = 0 */
505 outb(0x3c6, 0xff);
506 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
507 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize);
508 __VGLMouseMode(mousemode);
509 break;
510
511 case VIDBUF4:
512 case VIDBUF4S:
513 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
514 /* XXX works only for Xsize % 8 = 0 */
515 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
516 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */
517 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */
518 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */
519 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) {
520 VGLSetSegment(offset);
521 len = min(object->VXsize*object->VYsize - offset,
522 VGLAdpInfo.va_window_size);
523 memset(object->Bitmap, (byte)color, len);
524 offset += len;
525 }
526 outb(0x3ce, 0x05); outb(0x3cf, 0x00);
527 __VGLMouseMode(mousemode);
528 break;
529 }
530 if (object == VGLDisplay)
531 VGLMouseUnFreeze();
532 }
533
534 static inline u_long
VGLrgbToNative(uint16_t r,uint16_t g,uint16_t b)535 VGLrgbToNative(uint16_t r, uint16_t g, uint16_t b)
536 {
537 int nr, ng, nb;
538
539 nr = VGLModeInfo.vi_pixel_fsizes[2];
540 ng = VGLModeInfo.vi_pixel_fsizes[1];
541 nb = VGLModeInfo.vi_pixel_fsizes[0];
542 return (r >> (16 - nr) << (ng + nb)) | (g >> (16 - ng) << nb) |
543 (b >> (16 - nb) << 0);
544 }
545
546 u_long
VGLrgb332ToNative(byte c)547 VGLrgb332ToNative(byte c)
548 {
549 uint16_t r, g, b;
550
551 /* 3:3:2 to 16:16:16 */
552 r = ((c & 0xe0) >> 5) * 0xffff / 7;
553 g = ((c & 0x1c) >> 2) * 0xffff / 7;
554 b = ((c & 0x03) >> 0) * 0xffff / 3;
555
556 return VGLrgbToNative(r, g, b);
557 }
558
559 void
VGLRestorePalette()560 VGLRestorePalette()
561 {
562 int i;
563
564 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
565 return;
566 outb(0x3C6, 0xFF);
567 inb(0x3DA);
568 outb(0x3C8, 0x00);
569 for (i=0; i<256; i++) {
570 outb(0x3C9, VGLSavePaletteRed[i]);
571 inb(0x84);
572 outb(0x3C9, VGLSavePaletteGreen[i]);
573 inb(0x84);
574 outb(0x3C9, VGLSavePaletteBlue[i]);
575 inb(0x84);
576 }
577 inb(0x3DA);
578 outb(0x3C0, 0x20);
579 }
580
581 void
VGLSavePalette()582 VGLSavePalette()
583 {
584 int i;
585
586 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
587 return;
588 outb(0x3C6, 0xFF);
589 inb(0x3DA);
590 outb(0x3C7, 0x00);
591 for (i=0; i<256; i++) {
592 VGLSavePaletteRed[i] = inb(0x3C9);
593 inb(0x84);
594 VGLSavePaletteGreen[i] = inb(0x3C9);
595 inb(0x84);
596 VGLSavePaletteBlue[i] = inb(0x3C9);
597 inb(0x84);
598 }
599 inb(0x3DA);
600 outb(0x3C0, 0x20);
601 }
602
603 void
VGLSetPalette(byte * red,byte * green,byte * blue)604 VGLSetPalette(byte *red, byte *green, byte *blue)
605 {
606 int i;
607
608 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
609 return;
610 for (i=0; i<256; i++) {
611 VGLSavePaletteRed[i] = red[i];
612 VGLSavePaletteGreen[i] = green[i];
613 VGLSavePaletteBlue[i] = blue[i];
614 }
615 VGLCheckSwitch();
616 outb(0x3C6, 0xFF);
617 inb(0x3DA);
618 outb(0x3C8, 0x00);
619 for (i=0; i<256; i++) {
620 outb(0x3C9, VGLSavePaletteRed[i]);
621 inb(0x84);
622 outb(0x3C9, VGLSavePaletteGreen[i]);
623 inb(0x84);
624 outb(0x3C9, VGLSavePaletteBlue[i]);
625 inb(0x84);
626 }
627 inb(0x3DA);
628 outb(0x3C0, 0x20);
629 }
630
631 void
VGLSetPaletteIndex(byte color,byte red,byte green,byte blue)632 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue)
633 {
634 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
635 return;
636 VGLSavePaletteRed[color] = red;
637 VGLSavePaletteGreen[color] = green;
638 VGLSavePaletteBlue[color] = blue;
639 VGLCheckSwitch();
640 outb(0x3C6, 0xFF);
641 inb(0x3DA);
642 outb(0x3C8, color);
643 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue);
644 inb(0x3DA);
645 outb(0x3C0, 0x20);
646 }
647
648 void
VGLRestoreBorder(void)649 VGLRestoreBorder(void)
650 {
651 VGLSetBorder(VGLBorderColor);
652 }
653
654 void
VGLSetBorder(byte color)655 VGLSetBorder(byte color)
656 {
657 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
658 return;
659 VGLCheckSwitch();
660 inb(0x3DA);
661 outb(0x3C0,0x11); outb(0x3C0, color);
662 inb(0x3DA);
663 outb(0x3C0, 0x20);
664 VGLBorderColor = color;
665 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
666 ioctl(0, KDDISABIO, 0);
667 }
668
669 void
VGLRestoreBlank(void)670 VGLRestoreBlank(void)
671 {
672 VGLBlankDisplay(VGLBlank);
673 }
674
675 void
VGLBlankDisplay(int blank)676 VGLBlankDisplay(int blank)
677 {
678 byte val;
679
680 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
681 return;
682 VGLCheckSwitch();
683 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
684 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
685 VGLBlank = blank;
686 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
687 ioctl(0, KDDISABIO, 0);
688 }
689