2 * Copyright (c) 1991-1997 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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.
28 * $FreeBSD: src/lib/libvgl/main.c,v 1.6.2.2 2001/07/30 14:31:30 yokota Exp $
32 #include <sys/types.h>
33 #include <sys/signal.h>
35 #include <sys/ioctl.h>
37 #include <machine/console.h>
40 #define min(x, y) (((x) < (y)) ? (x) : (y))
41 #define max(x, y) (((x) > (y)) ? (x) : (y))
43 VGLBitmap
*VGLDisplay
;
44 video_info_t VGLModeInfo
;
45 video_adapter_info_t VGLAdpInfo
;
49 static int VGLOldMode
;
50 static size_t VGLBufSize
;
51 static byte
*VGLMem
= MAP_FAILED
;
52 static int VGLSwitchPending
;
53 static int VGLAbortPending
;
54 static int VGLOnDisplay
;
55 static unsigned int VGLCurWindow
;
56 static int VGLInitDone
= 0;
69 signal(SIGUSR1
, SIG_IGN
);
71 if (VGLMem
!= MAP_FAILED
) {
72 VGLClear(VGLDisplay
, 0);
73 munmap(VGLMem
, VGLAdpInfo
.va_window_size
);
76 ioctl(0, _IO('S', VGLOldMode
), 0);
77 ioctl(0, KDDISABIO
, 0);
78 ioctl(0, KDSETMODE
, KD_TEXT
);
80 ioctl(0, VT_SETMODE
, &smode
);
90 VGLAbort(int signo __unused
)
93 signal(SIGINT
, SIG_IGN
);
94 signal(SIGTERM
, SIG_IGN
);
95 signal(SIGSEGV
, SIG_IGN
);
96 signal(SIGBUS
, SIG_IGN
);
97 signal(SIGUSR2
, SIG_IGN
);
101 VGLSwitch(int signo __unused
)
107 VGLSwitchPending
= 1;
108 signal(SIGUSR1
, VGLSwitch
);
114 struct vt_mode smode
;
120 signal(SIGUSR1
, VGLSwitch
);
121 signal(SIGINT
, VGLAbort
);
122 signal(SIGTERM
, VGLAbort
);
123 signal(SIGSEGV
, VGLAbort
);
124 signal(SIGBUS
, VGLAbort
);
125 signal(SIGUSR2
, SIG_IGN
);
128 VGLSwitchPending
= 0;
131 if (ioctl(0, CONS_GET
, &VGLOldMode
) || ioctl(0, CONS_CURRENT
, &adptype
))
133 VGLModeInfo
.vi_mode
= mode
;
134 if (ioctl(0, CONS_MODEINFO
, &VGLModeInfo
)) /* FBIO_MODEINFO */
137 VGLDisplay
= (VGLBitmap
*)malloc(sizeof(VGLBitmap
));
138 if (VGLDisplay
== NULL
)
141 if (ioctl(0, KDENABIO
, 0)) {
149 * vi_mem_model specifies the memory model of the current video mode
152 switch (VGLModeInfo
.vi_mem_model
) {
153 case V_INFO_MM_PLANAR
:
154 /* we can handle EGA/VGA planner modes only */
155 if (VGLModeInfo
.vi_depth
!= 4 || VGLModeInfo
.vi_planes
!= 4
156 || (adptype
!= KD_EGA
&& adptype
!= KD_VGA
)) {
160 VGLDisplay
->Type
= VIDBUF4
;
162 case V_INFO_MM_PACKED
:
163 /* we can do only 256 color packed modes */
164 if (VGLModeInfo
.vi_depth
!= 8) {
168 VGLDisplay
->Type
= VIDBUF8
;
171 VGLDisplay
->Type
= VIDBUF8X
;
178 ioctl(0, VT_WAITACTIVE
, 0);
179 ioctl(0, KDSETMODE
, KD_GRAPHICS
);
180 if (ioctl(0, CONS_SET
, &mode
)) {
184 if (ioctl(0, CONS_ADPINFO
, &VGLAdpInfo
)) { /* FBIO_ADPINFO */
190 * Calculate the shadow screen buffer size. In -CURRENT, va_buffer_size
191 * always holds the entire frame buffer size, wheather it's in the linear
192 * mode or windowed mode.
193 * VGLBufSize = VGLAdpInfo.va_buffer_size;
194 * In -STABLE, va_buffer_size holds the frame buffer size, only if
195 * the linear frame buffer mode is supported. Otherwise the field is zero.
196 * We shall calculate the minimal size in this case:
197 * VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*VGLModeInfo.vi_planes
199 * VGLAdpInfo.va_window_size*VGLModeInfo.vi_planes;
200 * Use whichever is larger.
202 if (VGLAdpInfo
.va_buffer_size
!= 0)
203 VGLBufSize
= VGLAdpInfo
.va_buffer_size
;
205 VGLBufSize
= max(VGLAdpInfo
.va_line_width
*VGLModeInfo
.vi_height
,
206 VGLAdpInfo
.va_window_size
)*VGLModeInfo
.vi_planes
;
207 VGLBuf
= malloc(VGLBufSize
);
208 if (VGLBuf
== NULL
) {
214 fprintf(stderr
, "VGLBufSize:0x%x\n", VGLBufSize
);
217 /* see if we are in the windowed buffer mode or in the linear buffer mode */
218 if (VGLBufSize
/VGLModeInfo
.vi_planes
> VGLAdpInfo
.va_window_size
) {
219 if (VGLDisplay
->Type
== VIDBUF4
)
220 VGLDisplay
->Type
= VIDBUF4S
;
221 else if (VGLDisplay
->Type
== VIDBUF8
)
222 VGLDisplay
->Type
= VIDBUF8S
;
228 VGLDisplay
->Xsize
= VGLModeInfo
.vi_width
;
229 VGLDisplay
->Ysize
= VGLModeInfo
.vi_height
;
230 VGLDisplay
->VXsize
= VGLAdpInfo
.va_line_width
231 *8/(VGLModeInfo
.vi_depth
/VGLModeInfo
.vi_planes
);
232 VGLDisplay
->VYsize
= VGLBufSize
/VGLModeInfo
.vi_planes
/VGLAdpInfo
.va_line_width
;
233 VGLDisplay
->Xorigin
= 0;
234 VGLDisplay
->Yorigin
= 0;
236 VGLMem
= (byte
*)mmap(0, VGLAdpInfo
.va_window_size
, PROT_READ
|PROT_WRITE
,
238 if (VGLMem
== MAP_FAILED
) {
242 VGLDisplay
->Bitmap
= VGLMem
;
247 fprintf(stderr
, "va_line_width:%d\n", VGLAdpInfo
.va_line_width
);
248 fprintf(stderr
, "VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
249 VGLDisplay
->Xsize
, VGLDisplay
->Ysize
,
250 VGLDisplay
->VXsize
, VGLDisplay
->VYsize
);
253 smode
.mode
= VT_PROCESS
;
255 smode
.relsig
= SIGUSR1
;
256 smode
.acqsig
= SIGUSR1
;
257 smode
.frsig
= SIGINT
;
258 if (ioctl(0, VT_SETMODE
, &smode
)) {
262 VGLTextSetFontFile(NULL
);
263 VGLClear(VGLDisplay
, 0);
270 if (VGLAbortPending
) {
274 while (VGLSwitchPending
) {
279 VGLSwitchPending
= 0;
281 ioctl(0, KDENABIO
, 0);
282 ioctl(0, KDSETMODE
, KD_GRAPHICS
);
283 ioctl(0, VGLMode
, 0);
285 VGLMem
= (byte
*)mmap(0, VGLAdpInfo
.va_window_size
, PROT_READ
|PROT_WRITE
,
288 /* XXX: what if mmap() has failed! */
289 VGLDisplay
->Type
= VIDBUF8
; /* XXX */
290 switch (VGLModeInfo
.vi_mem_model
) {
291 case V_INFO_MM_PLANAR
:
292 if (VGLModeInfo
.vi_depth
== 4 && VGLModeInfo
.vi_planes
== 4) {
293 if (VGLBufSize
/VGLModeInfo
.vi_planes
> VGLAdpInfo
.va_window_size
)
294 VGLDisplay
->Type
= VIDBUF4S
;
296 VGLDisplay
->Type
= VIDBUF4
;
298 /* shouldn't be happening */
301 case V_INFO_MM_PACKED
:
302 if (VGLModeInfo
.vi_depth
== 8) {
303 if (VGLBufSize
/VGLModeInfo
.vi_planes
> VGLAdpInfo
.va_window_size
)
304 VGLDisplay
->Type
= VIDBUF8S
;
306 VGLDisplay
->Type
= VIDBUF8
;
308 /* shouldn't be happening */
312 VGLDisplay
->Type
= VIDBUF8X
;
315 /* shouldn't be happening */
319 VGLDisplay
->Bitmap
= VGLMem
;
320 VGLDisplay
->Xsize
= VGLModeInfo
.vi_width
;
321 VGLDisplay
->Ysize
= VGLModeInfo
.vi_height
;
322 VGLSetVScreenSize(VGLDisplay
, VGLDisplay
->VXsize
, VGLDisplay
->VYsize
);
323 VGLPanScreen(VGLDisplay
, VGLDisplay
->Xorigin
, VGLDisplay
->Yorigin
);
324 switch (VGLDisplay
->Type
) {
327 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */
328 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */
329 for (offset
= 0; offset
< VGLBufSize
/VGLModeInfo
.vi_planes
;
331 VGLSetSegment(offset
);
332 len
= min(VGLBufSize
/VGLModeInfo
.vi_planes
- offset
,
333 VGLAdpInfo
.va_window_size
);
334 for (i
= 0; i
< VGLModeInfo
.vi_planes
; i
++) {
336 outb(0x3c5, 0x01<<i
);
337 bcopy(&VGLBuf
[i
*VGLBufSize
/VGLModeInfo
.vi_planes
+ offset
],
345 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */
346 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */
347 for (i
= 0; i
< VGLModeInfo
.vi_planes
; i
++) {
349 outb(0x3c5, 0x01<<i
);
350 bcopy(&VGLBuf
[i
*VGLAdpInfo
.va_window_size
], VGLMem
,
351 VGLAdpInfo
.va_window_size
);
356 for (offset
= 0; offset
< VGLBufSize
; offset
+= len
) {
357 VGLSetSegment(offset
);
358 len
= min(VGLBufSize
- offset
, VGLAdpInfo
.va_window_size
);
359 bcopy(&VGLBuf
[offset
], VGLMem
, len
);
364 ioctl(0, VT_RELDISP
, VT_ACKACQ
);
367 switch (VGLDisplay
->Type
) {
369 for (offset
= 0; offset
< VGLBufSize
/VGLModeInfo
.vi_planes
;
371 VGLSetSegment(offset
);
372 len
= min(VGLBufSize
/VGLModeInfo
.vi_planes
- offset
,
373 VGLAdpInfo
.va_window_size
);
374 for (i
= 0; i
< VGLModeInfo
.vi_planes
; i
++) {
377 bcopy(VGLMem
, &VGLBuf
[i
*VGLBufSize
/VGLModeInfo
.vi_planes
+ offset
],
385 * NOTE: the saved buffer is NOT in the MEMBUF format which
386 * the ordinary memory bitmap object is stored in. XXX
388 for (i
= 0; i
< VGLModeInfo
.vi_planes
; i
++) {
391 bcopy(VGLMem
, &VGLBuf
[i
*VGLAdpInfo
.va_window_size
],
392 VGLAdpInfo
.va_window_size
);
397 for (offset
= 0; offset
< VGLBufSize
; offset
+= len
) {
398 VGLSetSegment(offset
);
399 len
= min(VGLBufSize
- offset
, VGLAdpInfo
.va_window_size
);
400 bcopy(VGLMem
, &VGLBuf
[offset
], len
);
405 munmap(VGLDisplay
->Bitmap
, VGLAdpInfo
.va_window_size
);
406 ioctl(0, VGLOldMode
, 0);
407 ioctl(0, KDSETMODE
, KD_TEXT
);
408 ioctl(0, KDDISABIO
, 0);
409 ioctl(0, VT_RELDISP
, VT_TRUE
);
410 VGLDisplay
->Bitmap
= VGLBuf
;
411 VGLDisplay
->Type
= MEMBUF
;
412 VGLDisplay
->Xsize
= VGLDisplay
->VXsize
;
413 VGLDisplay
->Ysize
= VGLDisplay
->VYsize
;
414 while (!VGLOnDisplay
) pause();
420 VGLSetSegment(unsigned int offset
)
422 if (offset
/VGLAdpInfo
.va_window_size
!= VGLCurWindow
) {
423 ioctl(0, CONS_SETWINORG
, offset
); /* FBIO_SETWINORG */
424 VGLCurWindow
= offset
/VGLAdpInfo
.va_window_size
;
426 return (offset
%VGLAdpInfo
.va_window_size
);
430 VGLSetVScreenSize(VGLBitmap
*object
, int VXsize
, int VYsize
)
432 if (VXsize
< object
->Xsize
|| VYsize
< object
->Ysize
)
434 if (object
->Type
== MEMBUF
)
436 if (ioctl(0, FBIO_SETLINEWIDTH
, &VXsize
))
438 ioctl(0, CONS_ADPINFO
, &VGLAdpInfo
); /* FBIO_ADPINFO */
439 object
->VXsize
= VGLAdpInfo
.va_line_width
440 *8/(VGLModeInfo
.vi_depth
/VGLModeInfo
.vi_planes
);
441 object
->VYsize
= VGLBufSize
/VGLModeInfo
.vi_planes
/VGLAdpInfo
.va_line_width
;
442 if (VYsize
< object
->VYsize
)
443 object
->VYsize
= VYsize
;
446 fprintf(stderr
, "new size: VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
447 object
->Xsize
, object
->Ysize
, object
->VXsize
, object
->VYsize
);
454 VGLPanScreen(VGLBitmap
*object
, int x
, int y
)
456 video_display_start_t origin
;
458 if (x
< 0 || x
+ object
->Xsize
> object
->VXsize
459 || y
< 0 || y
+ object
->Ysize
> object
->VYsize
)
461 if (object
->Type
== MEMBUF
)
465 if (ioctl(0, FBIO_SETDISPSTART
, &origin
))
471 fprintf(stderr
, "new origin: (%d, %d)\n", x
, y
);