2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1991-1997 Søren Schmidt
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #include <sys/endian.h>
40 static byte VGLSavePaletteRed[256];
41 static byte VGLSavePaletteGreen[256];
42 static byte VGLSavePaletteBlue[256];
44 #define ABS(a) (((a)<0) ? -(a) : (a))
45 #define SGN(a) (((a)<0) ? -1 : 1)
46 #define min(x, y) (((x) < (y)) ? (x) : (y))
47 #define max(x, y) (((x) > (y)) ? (x) : (y))
50 VGLSetXY(VGLBitmap *object, int x, int y, u_long color)
55 if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) {
56 if (object->Type == MEMBUF ||
57 !VGLMouseFreeze(x, y, 1, 1, 0x80000000 | color)) {
58 offset = (y * object->VXsize + x) * object->PixelBytes;
59 switch (object->Type) {
64 offset = VGLSetSegment(offset);
71 color = htole32(color);
72 switch (object->PixelBytes) {
74 memcpy(&object->Bitmap[offset], &color, 1);
77 memcpy(&object->Bitmap[offset], &color, 2);
80 memcpy(&object->Bitmap[offset], &color, 3);
83 memcpy(&object->Bitmap[offset], &color, 4);
89 outb(0x3c5, 0x01 << (x&0x3));
90 object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color);
93 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8);
96 offset = y*VGLAdpInfo.va_line_width + x/8;
98 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
99 outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f); /* set/reset */
100 outb(0x3ce, 0x01); outb(0x3cf, 0x0f); /* set/reset enable */
101 outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8)); /* bit mask */
102 object->Bitmap[offset] |= (byte)color;
105 if (object->Type != MEMBUF)
111 __VGLGetXY(VGLBitmap *object, int x, int y)
118 offset = (y * object->VXsize + x) * object->PixelBytes;
119 switch (object->Type) {
124 offset = VGLSetSegment(offset);
131 switch (object->PixelBytes) {
133 memcpy(&color, &object->Bitmap[offset], 1);
134 return le32toh(color) & 0xff;
136 memcpy(&color, &object->Bitmap[offset], 2);
137 return le32toh(color) & 0xffff;
139 memcpy(&color, &object->Bitmap[offset], 3);
140 return le32toh(color) & 0xffffff;
142 memcpy(&color, &object->Bitmap[offset], 4);
143 return le32toh(color);
147 outb(0x3ce, 0x04); outb(0x3cf, x & 0x3);
148 return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)];
150 offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8);
153 offset = y*VGLAdpInfo.va_line_width + x/8;
156 mask = 0x80 >> (x%8);
157 for (i = 0; i < VGLModeInfo.vi_planes; i++) {
158 outb(0x3ce, 0x04); outb(0x3cf, i);
159 color |= (((volatile VGLBitmap *)object)->Bitmap[offset] & mask) ?
164 return 0; /* XXX black? */
168 VGLGetXY(VGLBitmap *object, int x, int y)
173 if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize)
175 if (object->Type != MEMBUF) {
176 color = VGLMouseFreeze(x, y, 1, 1, 0x40000000);
177 if (color & 0x40000000) {
179 return color & 0xffffff;
182 color = __VGLGetXY(object, x, y);
183 if (object->Type != MEMBUF)
189 * Symmetric Double Step Line Algorithm by Brian Wyvill from
190 * "Graphics Gems", Academic Press, 1990.
193 #define SL_SWAP(a,b) {a^=b; b^=a; a^=b;}
194 #define SL_ABSOLUTE(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
197 plot(VGLBitmap * object, int x, int y, int flag, u_long color)
199 /* non-zero flag indicates the pixels need swapping back. */
201 VGLSetXY(object, y, x, color);
203 VGLSetXY(object, x, y, color);
208 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
210 int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
211 int sign_x, sign_y, step, reverse, i;
213 dx = SL_ABSOLUTE(x2, x1, sign_x);
214 dy = SL_ABSOLUTE(y2, y1, sign_y);
215 /* decide increment sign by the slope sign */
216 if (sign_x == sign_y)
221 if (dy > dx) { /* chooses axis of greatest movement (make dx) */
228 /* note error check for dx==0 should be included here */
229 if (x1 > x2) { /* start from the smaller coordinate */
242 /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
243 /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
244 /* In fact (dx-1)/4 as 2 pixels are already plotted */
246 pixels_left = (dx - 1) % 4; /* number of pixels left over at the
248 plot(object, x, y, reverse, color);
250 return; /* plot only one pixel for zero length
252 plot(object, x1, y1, reverse, color); /* plot first two points */
253 incr2 = 4 * dy - 2 * dx;
254 if (incr2 < 0) { /* slope less than 1/2 */
259 for (i = 0; i < xend; i++) { /* plotting loop */
263 /* pattern 1 forwards */
264 plot(object, x, y, reverse, color);
265 plot(object, ++x, y, reverse, color);
266 /* pattern 1 backwards */
267 plot(object, x1, y1, reverse, color);
268 plot(object, --x1, y1, reverse, color);
272 /* pattern 2 forwards */
273 plot(object, x, y, reverse, color);
274 plot(object, ++x, y += step, reverse,
276 /* pattern 2 backwards */
277 plot(object, x1, y1, reverse, color);
278 plot(object, --x1, y1 -= step, reverse,
281 /* pattern 3 forwards */
282 plot(object, x, y += step, reverse, color);
283 plot(object, ++x, y, reverse, color);
284 /* pattern 3 backwards */
285 plot(object, x1, y1 -= step, reverse,
287 plot(object, --x1, y1, reverse, color);
293 /* plot last pattern */
296 plot(object, ++x, y, reverse, color); /* pattern 1 */
298 plot(object, ++x, y, reverse, color);
300 plot(object, --x1, y1, reverse, color);
303 plot(object, ++x, y, reverse, color); /* pattern 2 */
305 plot(object, ++x, y += step, reverse, color);
307 plot(object, --x1, y1, reverse, color);
310 plot(object, ++x, y += step, reverse, color);
312 plot(object, ++x, y, reverse, color);
314 plot(object, --x1, y1 -= step, reverse, color);
317 } /* end if pixels_left */
319 /* end slope < 1/2 */
320 else { /* slope greater than 1/2 */
324 for (i = 0; i < xend; i++) {
328 /* pattern 4 forwards */
329 plot(object, x, y += step, reverse, color);
330 plot(object, ++x, y += step, reverse, color);
331 /* pattern 4 backwards */
332 plot(object, x1, y1 -= step, reverse, color);
333 plot(object, --x1, y1 -= step, reverse, color);
337 /* pattern 2 forwards */
338 plot(object, x, y, reverse, color);
339 plot(object, ++x, y += step, reverse,
342 /* pattern 2 backwards */
343 plot(object, x1, y1, reverse, color);
344 plot(object, --x1, y1 -= step, reverse,
347 /* pattern 3 forwards */
348 plot(object, x, y += step, reverse, color);
349 plot(object, ++x, y, reverse, color);
350 /* pattern 3 backwards */
351 plot(object, x1, y1 -= step, reverse, color);
352 plot(object, --x1, y1, reverse, color);
357 /* plot last pattern */
360 plot(object, ++x, y += step, reverse, color); /* pattern 4 */
362 plot(object, ++x, y += step, reverse,
365 plot(object, --x1, y1 -= step, reverse,
369 plot(object, ++x, y, reverse, color); /* pattern 2 */
371 plot(object, ++x, y += step, reverse, color);
373 plot(object, --x1, y1, reverse, color);
376 plot(object, ++x, y += step, reverse, color);
378 plot(object, ++x, y, reverse, color);
379 if (pixels_left > 2) {
380 if (D > c) /* step 3 */
381 plot(object, --x1, y1 -= step, reverse, color);
383 plot(object, --x1, y1, reverse, color);
392 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
394 VGLLine(object, x1, y1, x2, y1, color);
395 VGLLine(object, x2, y1, x2, y2, color);
396 VGLLine(object, x2, y2, x1, y2, color);
397 VGLLine(object, x1, y2, x1, y1, color);
401 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
405 for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color);
409 set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
412 VGLSetXY(object, xc+x, yc+y, color);
413 VGLSetXY(object, xc-x, yc+y, color);
415 VGLSetXY(object, xc+x, yc-y, color);
416 VGLSetXY(object, xc-x, yc-y, color);
420 VGLSetXY(object, xc, yc+y, color);
422 VGLSetXY(object, xc, yc-y, color);
427 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
429 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
430 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
433 set4pixels(object, x, y, xc, yc, color);
435 y--; dy-=asq2; d-=dy;
437 x++; dx+=bsq2; d+=bsq+dx;
439 d+=(3*(asq-bsq)/2-(dx+dy))/2;
441 set4pixels(object, x, y, xc, yc, color);
443 x++; dx+=bsq2; d+=dx;
445 y--; dy-=asq2; d+=asq-dy;
450 set2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
453 VGLLine(object, xc+x, yc+y, xc-x, yc+y, color);
455 VGLLine(object, xc+x, yc-y, xc-x, yc-y, color);
458 VGLLine(object, xc, yc+y, xc, yc-y, color);
463 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
465 int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
466 int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
469 set2lines(object, x, y, xc, yc, color);
471 y--; dy-=asq2; d-=dy;
473 x++; dx+=bsq2; d+=bsq+dx;
475 d+=(3*(asq-bsq)/2-(dx+dy))/2;
477 set2lines(object, x, y, xc, yc, color);
479 x++; dx+=bsq2; d+=dx;
481 y--; dy-=asq2; d+=asq-dy;
486 VGLClear(VGLBitmap *object, u_long color)
494 if (object->Type != MEMBUF)
495 VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color);
496 switch (object->Type) {
507 src.Xsize = object->Xsize;
508 src.VXsize = object->VXsize;
513 src.Bitmap = alloca(object->VXsize * object->PixelBytes);
514 src.PixelBytes = object->PixelBytes;
515 color = htole32(color);
516 for (i = 0; i < object->VXsize; i++)
517 bcopy(&color, src.Bitmap + i * object->PixelBytes, object->PixelBytes);
518 for (i = 0; i < object->VYsize; i++)
519 __VGLBitmapCopy(&src, 0, 0, object, 0, i, object->VXsize, 1);
523 /* XXX works only for Xsize % 4 = 0 */
525 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
526 memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize);
531 /* XXX works only for Xsize % 8 = 0 */
532 outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
533 outb(0x3ce, 0x05); outb(0x3cf, 0x02); /* mode 2 */
534 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */
535 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */
536 for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) {
537 VGLSetSegment(offset);
538 len = min(object->VXsize*object->VYsize - offset,
539 VGLAdpInfo.va_window_size);
540 memset(object->Bitmap, (byte)color, len);
543 outb(0x3ce, 0x05); outb(0x3cf, 0x00);
546 if (object->Type != MEMBUF)
555 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
560 for (i=0; i<256; i++) {
561 outb(0x3C9, VGLSavePaletteRed[i]);
563 outb(0x3C9, VGLSavePaletteGreen[i]);
565 outb(0x3C9, VGLSavePaletteBlue[i]);
577 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
582 for (i=0; i<256; i++) {
583 VGLSavePaletteRed[i] = inb(0x3C9);
585 VGLSavePaletteGreen[i] = inb(0x3C9);
587 VGLSavePaletteBlue[i] = inb(0x3C9);
595 VGLSetPalette(byte *red, byte *green, byte *blue)
599 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
601 for (i=0; i<256; i++) {
602 VGLSavePaletteRed[i] = red[i];
603 VGLSavePaletteGreen[i] = green[i];
604 VGLSavePaletteBlue[i] = blue[i];
610 for (i=0; i<256; i++) {
611 outb(0x3C9, VGLSavePaletteRed[i]);
613 outb(0x3C9, VGLSavePaletteGreen[i]);
615 outb(0x3C9, VGLSavePaletteBlue[i]);
623 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue)
625 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
627 VGLSavePaletteRed[color] = red;
628 VGLSavePaletteGreen[color] = green;
629 VGLSavePaletteBlue[color] = blue;
634 outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue);
640 VGLSetBorder(byte color)
642 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
646 outb(0x3C0,0x11); outb(0x3C0, color);
649 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
650 ioctl(0, KDDISABIO, 0);
654 VGLBlankDisplay(int blank)
658 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT && ioctl(0, KDENABIO, 0))
661 outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
662 outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
663 if (VGLModeInfo.vi_mem_model == V_INFO_MM_DIRECT)
664 ioctl(0, KDDISABIO, 0);