128328Ssos/*-
2229784Suqs * Copyright (c) 1991-1997 S��ren Schmidt
328328Ssos * All rights reserved.
428328Ssos *
528328Ssos * Redistribution and use in source and binary forms, with or without
628328Ssos * modification, are permitted provided that the following conditions
728328Ssos * are met:
828328Ssos * 1. Redistributions of source code must retain the above copyright
928328Ssos *    notice, this list of conditions and the following disclaimer
1028328Ssos *    in this position and unchanged.
1128328Ssos * 2. Redistributions in binary form must reproduce the above copyright
1228328Ssos *    notice, this list of conditions and the following disclaimer in the
1328328Ssos *    documentation and/or other materials provided with the distribution.
1428328Ssos * 3. The name of the author may not be used to endorse or promote products
1597748Sschweikh *    derived from this software without specific prior written permission
1628328Ssos *
1728328Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1828328Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1928328Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2028328Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2128328Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2228328Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2328328Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2428328Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2528328Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2628328Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2728328Ssos */
2828328Ssos
2983551Sdillon#include <sys/cdefs.h>
3083551Sdillon__FBSDID("$FreeBSD$");
3183551Sdillon
3228328Ssos#include <signal.h>
3366834Sphk#include <sys/fbio.h>
3428328Ssos#include "vgl.h"
3528328Ssos
3628328Ssosstatic byte VGLSavePaletteRed[256];
3728328Ssosstatic byte VGLSavePaletteGreen[256];
3828328Ssosstatic byte VGLSavePaletteBlue[256];
3928328Ssos
4028328Ssos#define ABS(a)		(((a)<0) ? -(a) : (a))
4128328Ssos#define SGN(a)		(((a)<0) ? -1 : 1)
4253013Syokota#define min(x, y)	(((x) < (y)) ? (x) : (y))
4353013Syokota#define max(x, y)	(((x) > (y)) ? (x) : (y))
4428328Ssos
4570991Snsouchstatic void
4670991Snsouchcolor2mem(u_long color, byte *b, int len)
4770991Snsouch{
4870991Snsouch  switch (len) {
4970991Snsouch  case 4:
5070991Snsouch    b[3] = (color >> 24) & 0xff;
5170991Snsouch    /* fallthrough */
5270991Snsouch  case 3:
5370991Snsouch    b[2] = (color >> 16) & 0xff;
5470991Snsouch    /* fallthrough */
5570991Snsouch  case 2:
5670991Snsouch    b[1] = (color >> 8) & 0xff;
5770991Snsouch    /* fallthrough */
5870991Snsouch  case 1:
5970991Snsouch  default:
6070991Snsouch    b[0] = color & 0xff;
6170991Snsouch    break;
6270991Snsouch  }
6370991Snsouch
6470991Snsouch  return;
6570991Snsouch}
6670991Snsouch
6770991Snsouchstatic u_long
6870991Snsouchmem2color(byte *b, int len)
6970991Snsouch{
7070991Snsouch  u_long color = 0;
7170991Snsouch
7270991Snsouch  switch (len) {
7370991Snsouch  case 4:
7470991Snsouch    color |= (b[3] & 0xff) << 24;
7570991Snsouch    /* fallthrough */
7670991Snsouch  case 3:
7770991Snsouch    color |= (b[2] & 0xff) << 16;
7870991Snsouch    /* fallthrough */
7970991Snsouch  case 2:
8070991Snsouch    color |= (b[1] & 0xff) << 8;
8170991Snsouch    /* fallthrough */
8270991Snsouch  case 1:
8370991Snsouch  default:
8470991Snsouch    color |= (b[0] & 0xff);
8570991Snsouch    break;
8670991Snsouch  }
8770991Snsouch
8870991Snsouch  return color;
8970991Snsouch}
9070991Snsouch
9128328Ssosvoid
9270991SnsouchVGLSetXY(VGLBitmap *object, int x, int y, u_long color)
9328328Ssos{
9453013Syokota  int offset;
9570991Snsouch  byte b[4];
9653013Syokota
9728328Ssos  VGLCheckSwitch();
9853013Syokota  if (x>=0 && x<object->VXsize && y>=0 && y<object->VYsize) {
9928328Ssos    if (!VGLMouseFreeze(x, y, 1, 1, color)) {
10028328Ssos      switch (object->Type) {
10128328Ssos      case MEMBUF:
10228328Ssos      case VIDBUF8:
10370991Snsouch        object->Bitmap[y*object->VXsize+x]=((byte)color);
10428328Ssos        break;
10553013Syokota      case VIDBUF8S:
10670991Snsouch	object->Bitmap[VGLSetSegment(y*object->VXsize+x)]=((byte)color);
10753013Syokota	break;
10870991Snsouch      case VIDBUF16:
10970991Snsouch      case VIDBUF24:
11070991Snsouch      case VIDBUF32:
11170991Snsouch	color2mem(color, b, object->PixelBytes);
11270991Snsouch        bcopy(b, &object->Bitmap[(y*object->VXsize+x) * object->PixelBytes],
11370991Snsouch		object->PixelBytes);
11470991Snsouch        break;
11570991Snsouch      case VIDBUF16S:
11670991Snsouch      case VIDBUF24S:
11770991Snsouch      case VIDBUF32S:
11870991Snsouch	color2mem(color, b, object->PixelBytes);
11970991Snsouch	offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes);
12070991Snsouch	bcopy(b, &object->Bitmap[offset], object->PixelBytes);
12170991Snsouch	break;
12228328Ssos      case VIDBUF8X:
12328328Ssos        outb(0x3c4, 0x02);
12428328Ssos        outb(0x3c5, 0x01 << (x&0x3));
12570991Snsouch	object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)] = ((byte)color);
12628328Ssos	break;
12753013Syokota      case VIDBUF4S:
12853013Syokota	offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8);
12953013Syokota	goto set_planar;
13028328Ssos      case VIDBUF4:
13153013Syokota	offset = y*VGLAdpInfo.va_line_width + x/8;
13253013Syokotaset_planar:
13353013Syokota        outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
13470991Snsouch        outb(0x3ce, 0x00); outb(0x3cf, (byte)color & 0x0f);	/* set/reset */
13553013Syokota        outb(0x3ce, 0x01); outb(0x3cf, 0x0f);		/* set/reset enable */
13653013Syokota        outb(0x3ce, 0x08); outb(0x3cf, 0x80 >> (x%8));	/* bit mask */
13770991Snsouch	object->Bitmap[offset] |= (byte)color;
13828328Ssos      }
13928328Ssos    }
14028328Ssos    VGLMouseUnFreeze();
14128328Ssos  }
14228328Ssos}
14328328Ssos
14470991Snsouchu_long
14528328SsosVGLGetXY(VGLBitmap *object, int x, int y)
14628328Ssos{
14753013Syokota  int offset;
14870991Snsouch  byte b[4];
14953013Syokota#if 0
15053013Syokota  int i;
15170991Snsouch  u_long color;
15253013Syokota  byte mask;
15353013Syokota#endif
15453013Syokota
15528328Ssos  VGLCheckSwitch();
15653013Syokota  if (x<0 || x>=object->VXsize || y<0 || y>=object->VYsize)
15753013Syokota    return 0;
15828328Ssos  switch (object->Type) {
15928328Ssos    case MEMBUF:
16028328Ssos    case VIDBUF8:
16153013Syokota      return object->Bitmap[((y*object->VXsize)+x)];
16253013Syokota    case VIDBUF8S:
16353013Syokota      return object->Bitmap[VGLSetSegment(y*object->VXsize+x)];
16470991Snsouch    case VIDBUF16:
16570991Snsouch    case VIDBUF24:
16670991Snsouch    case VIDBUF32:
16770991Snsouch      bcopy(&object->Bitmap[(y*object->VXsize+x) * object->PixelBytes],
16870991Snsouch		b, object->PixelBytes);
16970991Snsouch      return (mem2color(b, object->PixelBytes));
17070991Snsouch    case VIDBUF16S:
17170991Snsouch    case VIDBUF24S:
17270991Snsouch    case VIDBUF32S:
17370991Snsouch	offset = VGLSetSegment((y*object->VXsize+x) * object->PixelBytes);
17470991Snsouch	bcopy(&object->Bitmap[offset], b, object->PixelBytes);
17570991Snsouch
17670991Snsouch      return (mem2color(b, object->PixelBytes));
17728328Ssos    case VIDBUF8X:
17828328Ssos      outb(0x3ce, 0x04); outb(0x3cf, x & 0x3);
17953013Syokota      return object->Bitmap[(unsigned)(VGLAdpInfo.va_line_width*y)+(x/4)];
18053013Syokota    case VIDBUF4S:
18153013Syokota      offset = VGLSetSegment(y*VGLAdpInfo.va_line_width + x/8);
18253013Syokota      goto get_planar;
18328328Ssos    case VIDBUF4:
18453013Syokota      offset = y*VGLAdpInfo.va_line_width + x/8;
18553013Syokotaget_planar:
18653013Syokota#if 1
18753013Syokota      return (object->Bitmap[offset]&(0x80>>(x%8))) ? 1 : 0;	/* XXX */
18853013Syokota#else
18953013Syokota      color = 0;
19053013Syokota      mask = 0x80 >> (x%8);
19153013Syokota      for (i = 0; i < VGLModeInfo.vi_planes; i++) {
19253013Syokota	outb(0x3ce, 0x04); outb(0x3cf, i);
19353013Syokota	color |= (object->Bitmap[offset] & mask) ? (1 << i) : 0;
19453013Syokota      }
19553013Syokota      return color;
19653013Syokota#endif
19728328Ssos  }
19870991Snsouch  return 0;		/* XXX black? */
19928328Ssos}
20028328Ssos
201229415Spfg /*
202229415Spfg  * Symmetric Double Step Line Algorithm by Brian Wyvill from
203229415Spfg  * "Graphics Gems", Academic Press, 1990.
204229415Spfg  */
205229415Spfg
206229415Spfg#define SL_SWAP(a,b)           {a^=b; b^=a; a^=b;}
207229415Spfg#define SL_ABSOLUTE(i,j,k)     ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
208229415Spfg
20928328Ssosvoid
210229415Spfgplot(VGLBitmap * object, int x, int y, int flag, byte color)
211229415Spfg{
212229415Spfg  /* non-zero flag indicates the pixels need swapping back. */
213229415Spfg  if (flag)
214229415Spfg    VGLSetXY(object, y, x, color);
215229415Spfg  else
216229415Spfg    VGLSetXY(object, x, y, color);
217229415Spfg}
218229415Spfg
219229415Spfg
220229415Spfgvoid
22170991SnsouchVGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
22228328Ssos{
223229415Spfg  int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
224229415Spfg  int sign_x, sign_y, step, reverse, i;
22528328Ssos
226229415Spfg  dx = SL_ABSOLUTE(x2, x1, sign_x);
227229415Spfg  dy = SL_ABSOLUTE(y2, y1, sign_y);
228229415Spfg  /* decide increment sign by the slope sign */
229229415Spfg  if (sign_x == sign_y)
230229415Spfg    step = 1;
231229415Spfg  else
232229415Spfg    step = -1;
23328328Ssos
234229415Spfg  if (dy > dx) {	/* chooses axis of greatest movement (make dx) */
235229415Spfg    SL_SWAP(x1, y1);
236229415Spfg    SL_SWAP(x2, y2);
237229415Spfg    SL_SWAP(dx, dy);
238229415Spfg    reverse = 1;
239229415Spfg  } else
240229415Spfg    reverse = 0;
241229415Spfg  /* note error check for dx==0 should be included here */
242229415Spfg  if (x1 > x2) {      /* start from the smaller coordinate */
243229415Spfg    x = x2;
244229415Spfg    y = y2;
245229516Spfg/*  x1 = x1;
246229516Spfg    y1 = y1; */
247229415Spfg  } else {
248229415Spfg    x = x1;
249229415Spfg    y = y1;
250229415Spfg    x1 = x2;
251229415Spfg    y1 = y2;
252229415Spfg  }
253229415Spfg
254229415Spfg
255229415Spfg  /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
256229415Spfg  /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
257229415Spfg  /* In fact (dx-1)/4 as 2 pixels are already plotted */
258229415Spfg  xend = (dx - 1) / 4;
259229415Spfg  pixels_left = (dx - 1) % 4;  /* number of pixels left over at the
260229415Spfg           * end */
261229415Spfg  plot(object, x, y, reverse, color);
262229415Spfg  if (pixels_left < 0)
263229415Spfg    return;      /* plot only one pixel for zero length
264229415Spfg           * vectors */
265229415Spfg  plot(object, x1, y1, reverse, color);  /* plot first two points */
266229415Spfg  incr2 = 4 * dy - 2 * dx;
267229415Spfg  if (incr2 < 0) {    /* slope less than 1/2 */
268229415Spfg    c = 2 * dy;
269229415Spfg    incr1 = 2 * c;
270229415Spfg    D = incr1 - dx;
271229415Spfg
272229415Spfg    for (i = 0; i < xend; i++) {  /* plotting loop */
273229415Spfg      ++x;
274229415Spfg      --x1;
275229415Spfg      if (D < 0) {
276229415Spfg        /* pattern 1 forwards */
277229415Spfg        plot(object, x, y, reverse, color);
278229415Spfg        plot(object, ++x, y, reverse, color);
279229415Spfg        /* pattern 1 backwards */
280229415Spfg        plot(object, x1, y1, reverse, color);
281229415Spfg        plot(object, --x1, y1, reverse, color);
282229415Spfg        D += incr1;
283229415Spfg      } else {
284229415Spfg        if (D < c) {
285229415Spfg          /* pattern 2 forwards */
286229415Spfg          plot(object, x, y, reverse, color);
287229415Spfg          plot(object, ++x, y += step, reverse,
288229415Spfg              color);
289229415Spfg          /* pattern 2 backwards */
290229415Spfg          plot(object, x1, y1, reverse, color);
291229415Spfg          plot(object, --x1, y1 -= step, reverse,
292229415Spfg              color);
293229415Spfg        } else {
294229415Spfg          /* pattern 3 forwards */
295229415Spfg          plot(object, x, y += step, reverse, color);
296229415Spfg          plot(object, ++x, y, reverse, color);
297229415Spfg          /* pattern 3 backwards */
298229415Spfg          plot(object, x1, y1 -= step, reverse,
299229415Spfg              color);
300229415Spfg          plot(object, --x1, y1, reverse, color);
301229415Spfg        }
302229415Spfg        D += incr2;
30328328Ssos      }
304229415Spfg    }      /* end for */
305229415Spfg
306229415Spfg    /* plot last pattern */
307229415Spfg    if (pixels_left) {
308229415Spfg      if (D < 0) {
309229415Spfg        plot(object, ++x, y, reverse, color);  /* pattern 1 */
310229415Spfg        if (pixels_left > 1)
311229415Spfg          plot(object, ++x, y, reverse, color);
312229415Spfg        if (pixels_left > 2)
313229415Spfg          plot(object, --x1, y1, reverse, color);
314229415Spfg      } else {
315229415Spfg        if (D < c) {
316229415Spfg          plot(object, ++x, y, reverse, color);  /* pattern 2  */
317229415Spfg          if (pixels_left > 1)
318229415Spfg            plot(object, ++x, y += step, reverse, color);
319229415Spfg          if (pixels_left > 2)
320229415Spfg            plot(object, --x1, y1, reverse, color);
321229415Spfg        } else {
322229415Spfg          /* pattern 3 */
323229415Spfg          plot(object, ++x, y += step, reverse, color);
324229415Spfg          if (pixels_left > 1)
325229415Spfg            plot(object, ++x, y, reverse, color);
326229415Spfg          if (pixels_left > 2)
327229415Spfg            plot(object, --x1, y1 -= step, reverse, color);
328229415Spfg        }
329229415Spfg      }
330229415Spfg    }      /* end if pixels_left */
33128328Ssos  }
332229415Spfg  /* end slope < 1/2 */
333229415Spfg  else {        /* slope greater than 1/2 */
334229415Spfg    c = 2 * (dy - dx);
335229415Spfg    incr1 = 2 * c;
336229415Spfg    D = incr1 + dx;
337229415Spfg    for (i = 0; i < xend; i++) {
338229415Spfg      ++x;
339229415Spfg      --x1;
340229415Spfg      if (D > 0) {
341229415Spfg        /* pattern 4 forwards */
342229415Spfg        plot(object, x, y += step, reverse, color);
343229415Spfg        plot(object, ++x, y += step, reverse, color);
344229415Spfg        /* pattern 4 backwards */
345229415Spfg        plot(object, x1, y1 -= step, reverse, color);
346229415Spfg        plot(object, --x1, y1 -= step, reverse, color);
347229415Spfg        D += incr1;
348229415Spfg      } else {
349229415Spfg        if (D < c) {
350229415Spfg          /* pattern 2 forwards */
351229415Spfg          plot(object, x, y, reverse, color);
352229415Spfg          plot(object, ++x, y += step, reverse,
353229415Spfg              color);
354229415Spfg
355229415Spfg          /* pattern 2 backwards */
356229415Spfg          plot(object, x1, y1, reverse, color);
357229415Spfg          plot(object, --x1, y1 -= step, reverse,
358229415Spfg              color);
359229415Spfg        } else {
360229415Spfg          /* pattern 3 forwards */
361229415Spfg          plot(object, x, y += step, reverse, color);
362229415Spfg          plot(object, ++x, y, reverse, color);
363229415Spfg          /* pattern 3 backwards */
364229415Spfg          plot(object, x1, y1 -= step, reverse, color);
365229415Spfg          plot(object, --x1, y1, reverse, color);
366229415Spfg        }
367229415Spfg        D += incr2;
36828328Ssos      }
369229415Spfg    }      /* end for */
370229415Spfg    /* plot last pattern */
371229415Spfg    if (pixels_left) {
372229415Spfg      if (D > 0) {
373229415Spfg        plot(object, ++x, y += step, reverse, color);  /* pattern 4 */
374229415Spfg        if (pixels_left > 1)
375229415Spfg          plot(object, ++x, y += step, reverse,
376229415Spfg              color);
377229415Spfg        if (pixels_left > 2)
378229415Spfg          plot(object, --x1, y1 -= step, reverse,
379229415Spfg              color);
380229415Spfg      } else {
381229415Spfg        if (D < c) {
382229415Spfg          plot(object, ++x, y, reverse, color);  /* pattern 2  */
383229415Spfg          if (pixels_left > 1)
384229415Spfg            plot(object, ++x, y += step, reverse, color);
385229415Spfg          if (pixels_left > 2)
386229415Spfg            plot(object, --x1, y1, reverse, color);
387229415Spfg        } else {
388229415Spfg          /* pattern 3 */
389229415Spfg          plot(object, ++x, y += step, reverse, color);
390229415Spfg          if (pixels_left > 1)
391229415Spfg            plot(object, ++x, y, reverse, color);
392229415Spfg          if (pixels_left > 2) {
393229415Spfg            if (D > c)  /* step 3 */
394229415Spfg              plot(object, --x1, y1 -= step, reverse, color);
395229415Spfg            else  /* step 2 */
396229415Spfg              plot(object, --x1, y1, reverse, color);
397229415Spfg          }
398229415Spfg        }
399229415Spfg      }
40028328Ssos    }
40128328Ssos  }
40228328Ssos}
40328328Ssos
40428328Ssosvoid
40570991SnsouchVGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
40628328Ssos{
40728328Ssos  VGLLine(object, x1, y1, x2, y1, color);
40828328Ssos  VGLLine(object, x2, y1, x2, y2, color);
40928328Ssos  VGLLine(object, x2, y2, x1, y2, color);
41028328Ssos  VGLLine(object, x1, y2, x1, y1, color);
41128328Ssos}
41228328Ssos
41328328Ssosvoid
41470991SnsouchVGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, u_long color)
41528328Ssos{
41628328Ssos  int y;
41728328Ssos
41828328Ssos  for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color);
41928328Ssos}
42028328Ssos
421213412Sdimstatic inline void
422213412Sdimset4pixels(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
42328328Ssos{
42428328Ssos  if (x!=0) {
42528328Ssos    VGLSetXY(object, xc+x, yc+y, color);
42628328Ssos    VGLSetXY(object, xc-x, yc+y, color);
42728328Ssos    if (y!=0) {
42828328Ssos      VGLSetXY(object, xc+x, yc-y, color);
42928328Ssos      VGLSetXY(object, xc-x, yc-y, color);
43028328Ssos    }
43128328Ssos  }
43228328Ssos  else {
43328328Ssos    VGLSetXY(object, xc, yc+y, color);
43428328Ssos    if (y!=0)
43528328Ssos      VGLSetXY(object, xc, yc-y, color);
43628328Ssos  }
43728328Ssos}
43828328Ssos
43928328Ssosvoid
44070991SnsouchVGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
44128328Ssos{
44228328Ssos  int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
44328328Ssos  int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
44428328Ssos
44528328Ssos  while (dx<dy) {
44628328Ssos    set4pixels(object, x, y, xc, yc, color);
44728328Ssos    if (d>0) {
44828328Ssos      y--; dy-=asq2; d-=dy;
44928328Ssos    }
45028328Ssos    x++; dx+=bsq2; d+=bsq+dx;
45128328Ssos  }
45228328Ssos  d+=(3*(asq-bsq)/2-(dx+dy))/2;
45328328Ssos  while (y>=0) {
45428328Ssos    set4pixels(object, x, y, xc, yc, color);
45528328Ssos    if (d<0) {
45628328Ssos      x++; dx+=bsq2; d+=dx;
45728328Ssos    }
45828328Ssos    y--; dy-=asq2; d+=asq-dy;
45928328Ssos  }
46028328Ssos}
46128328Ssos
462213412Sdimstatic inline void
463213412Sdimset2lines(VGLBitmap *object, int x, int y, int xc, int yc, u_long color)
46428328Ssos{
46528328Ssos  if (x!=0) {
46628328Ssos    VGLLine(object, xc+x, yc+y, xc-x, yc+y, color);
46728328Ssos    if (y!=0)
46828328Ssos      VGLLine(object, xc+x, yc-y, xc-x, yc-y, color);
46928328Ssos  }
47028328Ssos  else {
47128328Ssos    VGLLine(object, xc, yc+y, xc, yc-y, color);
47228328Ssos  }
47328328Ssos}
47428328Ssos
47528328Ssosvoid
47670991SnsouchVGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, u_long color)
47728328Ssos{
47828328Ssos  int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
47928328Ssos  int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
48028328Ssos
48128328Ssos  while (dx<dy) {
48228328Ssos    set2lines(object, x, y, xc, yc, color);
48328328Ssos    if (d>0) {
48428328Ssos      y--; dy-=asq2; d-=dy;
48528328Ssos    }
48628328Ssos    x++; dx+=bsq2; d+=bsq+dx;
48728328Ssos  }
48828328Ssos  d+=(3*(asq-bsq)/2-(dx+dy))/2;
48928328Ssos  while (y>=0) {
49028328Ssos    set2lines(object, x, y, xc, yc, color);
49128328Ssos    if (d<0) {
49228328Ssos      x++; dx+=bsq2; d+=dx;
49328328Ssos    }
49428328Ssos    y--; dy-=asq2; d+=asq-dy;
49528328Ssos  }
49628328Ssos}
49728328Ssos
49828328Ssosvoid
49970991SnsouchVGLClear(VGLBitmap *object, u_long color)
50028328Ssos{
50153013Syokota  int offset;
50253013Syokota  int len;
50370991Snsouch  int i, total = 0;
50470991Snsouch  byte b[4];
50553013Syokota
50628328Ssos  VGLCheckSwitch();
50770991Snsouch  VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color); /* XXX */
50828328Ssos  switch (object->Type) {
50928328Ssos  case MEMBUF:
51028328Ssos  case VIDBUF8:
51170991Snsouch    memset(object->Bitmap, (byte)color, object->VXsize*object->VYsize);
51228328Ssos    break;
51353013Syokota
51453013Syokota  case VIDBUF8S:
51553013Syokota    for (offset = 0; offset < object->VXsize*object->VYsize; ) {
51653013Syokota      VGLSetSegment(offset);
51753013Syokota      len = min(object->VXsize*object->VYsize - offset,
51853013Syokota		VGLAdpInfo.va_window_size);
51970991Snsouch      memset(object->Bitmap, (byte)color, len);
52053013Syokota      offset += len;
52153013Syokota    }
52253013Syokota    break;
52370991Snsouch  case VIDBUF16:
52470991Snsouch  case VIDBUF24:
52570991Snsouch  case VIDBUF32:
52670991Snsouch    color2mem(color, b, object->PixelBytes);
52770991Snsouch    total = object->VXsize*object->VYsize*object->PixelBytes;
52870991Snsouch    for (i = 0; i < total; i += object->PixelBytes)
52970991Snsouch      bcopy(b, object->Bitmap + i, object->PixelBytes);
53070991Snsouch    break;
53153013Syokota
53270991Snsouch  case VIDBUF16S:
53370991Snsouch  case VIDBUF24S:
53470991Snsouch  case VIDBUF32S:
53570991Snsouch    color2mem(color, b, object->PixelBytes);
53670991Snsouch    total = object->VXsize*object->VYsize*object->PixelBytes;
53770991Snsouch    for (offset = 0; offset < total; ) {
53870991Snsouch      VGLSetSegment(offset);
53970991Snsouch      len = min(total - offset, VGLAdpInfo.va_window_size);
54070991Snsouch      for (i = 0; i < len; i += object->PixelBytes)
54170991Snsouch	bcopy(b, object->Bitmap + offset + i, object->PixelBytes);
54270991Snsouch      offset += len;
54370991Snsouch    }
54470991Snsouch    break;
54570991Snsouch
54628328Ssos  case VIDBUF8X:
54728328Ssos    /* XXX works only for Xsize % 4 = 0 */
54853013Syokota    outb(0x3c6, 0xff);
54928328Ssos    outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
55070991Snsouch    memset(object->Bitmap, (byte)color, VGLAdpInfo.va_line_width*object->VYsize);
55128328Ssos    break;
55228328Ssos
55328328Ssos  case VIDBUF4:
55453013Syokota  case VIDBUF4S:
55528328Ssos    /* XXX works only for Xsize % 8 = 0 */
55653013Syokota    outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
55753013Syokota    outb(0x3ce, 0x05); outb(0x3cf, 0x02);		/* mode 2 */
55853013Syokota    outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
55953013Syokota    outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
56053013Syokota    for (offset = 0; offset < VGLAdpInfo.va_line_width*object->VYsize; ) {
56153013Syokota      VGLSetSegment(offset);
56253013Syokota      len = min(object->VXsize*object->VYsize - offset,
56353013Syokota		VGLAdpInfo.va_window_size);
56470991Snsouch      memset(object->Bitmap, (byte)color, len);
56553013Syokota      offset += len;
56653013Syokota    }
56753013Syokota    outb(0x3ce, 0x05); outb(0x3cf, 0x00);
56828328Ssos    break;
56928328Ssos  }
57028328Ssos  VGLMouseUnFreeze();
57128328Ssos}
57228328Ssos
57328328Ssosvoid
57428328SsosVGLRestorePalette()
57528328Ssos{
57628328Ssos  int i;
57728328Ssos
57828328Ssos  outb(0x3C6, 0xFF);
57928328Ssos  inb(0x3DA);
58028328Ssos  outb(0x3C8, 0x00);
58128328Ssos  for (i=0; i<256; i++) {
58228328Ssos    outb(0x3C9, VGLSavePaletteRed[i]);
58328328Ssos    inb(0x84);
58428328Ssos    outb(0x3C9, VGLSavePaletteGreen[i]);
58528328Ssos    inb(0x84);
58628328Ssos    outb(0x3C9, VGLSavePaletteBlue[i]);
58728328Ssos    inb(0x84);
58828328Ssos  }
58928328Ssos  inb(0x3DA);
59028328Ssos  outb(0x3C0, 0x20);
59128328Ssos}
59228328Ssos
59328328Ssosvoid
59428328SsosVGLSavePalette()
59528328Ssos{
59628328Ssos  int i;
59728328Ssos
59828328Ssos  outb(0x3C6, 0xFF);
59928328Ssos  inb(0x3DA);
60028328Ssos  outb(0x3C7, 0x00);
60128328Ssos  for (i=0; i<256; i++) {
60228328Ssos    VGLSavePaletteRed[i] = inb(0x3C9);
60328328Ssos    inb(0x84);
60428328Ssos    VGLSavePaletteGreen[i] = inb(0x3C9);
60528328Ssos    inb(0x84);
60628328Ssos    VGLSavePaletteBlue[i] = inb(0x3C9);
60728328Ssos    inb(0x84);
60828328Ssos  }
60928328Ssos  inb(0x3DA);
61028328Ssos  outb(0x3C0, 0x20);
61128328Ssos}
61228328Ssos
61328328Ssosvoid
61428328SsosVGLSetPalette(byte *red, byte *green, byte *blue)
61528328Ssos{
61628328Ssos  int i;
61728328Ssos
61828328Ssos  for (i=0; i<256; i++) {
61928328Ssos    VGLSavePaletteRed[i] = red[i];
62028328Ssos    VGLSavePaletteGreen[i] = green[i];
62128328Ssos    VGLSavePaletteBlue[i] = blue[i];
62228328Ssos  }
62328328Ssos  VGLCheckSwitch();
62428328Ssos  outb(0x3C6, 0xFF);
62528328Ssos  inb(0x3DA);
62628328Ssos  outb(0x3C8, 0x00);
62728328Ssos  for (i=0; i<256; i++) {
62828328Ssos    outb(0x3C9, VGLSavePaletteRed[i]);
62928328Ssos    inb(0x84);
63028328Ssos    outb(0x3C9, VGLSavePaletteGreen[i]);
63128328Ssos    inb(0x84);
63228328Ssos    outb(0x3C9, VGLSavePaletteBlue[i]);
63328328Ssos    inb(0x84);
63428328Ssos  }
63528328Ssos  inb(0x3DA);
63628328Ssos  outb(0x3C0, 0x20);
63728328Ssos}
63828328Ssos
63928328Ssosvoid
64028328SsosVGLSetPaletteIndex(byte color, byte red, byte green, byte blue)
64128328Ssos{
64228328Ssos  VGLSavePaletteRed[color] = red;
64328328Ssos  VGLSavePaletteGreen[color] = green;
64428328Ssos  VGLSavePaletteBlue[color] = blue;
64528328Ssos  VGLCheckSwitch();
64628328Ssos  outb(0x3C6, 0xFF);
64728328Ssos  inb(0x3DA);
64828328Ssos  outb(0x3C8, color);
64928328Ssos  outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue);
65028328Ssos  inb(0x3DA);
65128328Ssos  outb(0x3C0, 0x20);
65228328Ssos}
65328328Ssos
65428328Ssosvoid
65528328SsosVGLSetBorder(byte color)
65628328Ssos{
65728328Ssos  VGLCheckSwitch();
65828328Ssos  inb(0x3DA);
65928328Ssos  outb(0x3C0,0x11); outb(0x3C0, color);
66028328Ssos  inb(0x3DA);
66128328Ssos  outb(0x3C0, 0x20);
66228328Ssos}
66328328Ssos
66428328Ssosvoid
66528328SsosVGLBlankDisplay(int blank)
66628328Ssos{
66728328Ssos  byte val;
66828328Ssos
66928328Ssos  VGLCheckSwitch();
67028328Ssos  outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
67128328Ssos  outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
67228328Ssos}
673