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