main.c revision 80270
128328Ssos/*-
228328Ssos * 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
1528328Ssos *    derived from this software withough 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 *
2850476Speter * $FreeBSD: head/lib/libvgl/main.c 80270 2001-07-24 11:15:20Z yokota $
2928328Ssos */
3028328Ssos
3128328Ssos#include <stdio.h>
3228328Ssos#include <sys/types.h>
3328328Ssos#include <sys/signal.h>
3428328Ssos#include <sys/file.h>
3528328Ssos#include <sys/ioctl.h>
3628328Ssos#include <sys/mman.h>
3766834Sphk#include <sys/fbio.h>
3866834Sphk#include <sys/kbio.h>
3966834Sphk#include <sys/consio.h>
4028328Ssos#include "vgl.h"
4128328Ssos
4270991Snsouch/* XXX Direct Color 24bits modes unsupported */
4370991Snsouch
4453013Syokota#define min(x, y)	(((x) < (y)) ? (x) : (y))
4553013Syokota#define max(x, y)	(((x) > (y)) ? (x) : (y))
4653013Syokota
4728328SsosVGLBitmap *VGLDisplay;
4853013Syokotavideo_info_t VGLModeInfo;
4953013Syokotavideo_adapter_info_t VGLAdpInfo;
5053013Syokotabyte *VGLBuf;
5128328Ssos
5228328Ssosstatic int VGLMode;
5328328Ssosstatic int VGLOldMode;
5453013Syokotastatic size_t VGLBufSize;
5553013Syokotastatic byte *VGLMem = MAP_FAILED;
5628328Ssosstatic int VGLSwitchPending;
5780270Syokotastatic int VGLAbortPending;
5828328Ssosstatic int VGLOnDisplay;
5953013Syokotastatic unsigned int VGLCurWindow;
6030044Ssosstatic int VGLInitDone = 0;
6176852Ssobomaxstatic vid_info_t VGLOldVInfo;
6228328Ssos
6328328Ssosvoid
6428328SsosVGLEnd()
6528328Ssos{
6628328Ssosstruct vt_mode smode;
6728328Ssos
6830044Ssos  if (!VGLInitDone)
6930044Ssos    return;
7053013Syokota  VGLInitDone = 0;
7180270Syokota  VGLSwitchPending = 0;
7280270Syokota  VGLAbortPending = 0;
7353013Syokota
7453013Syokota  signal(SIGUSR1, SIG_IGN);
7553013Syokota
7653013Syokota  if (VGLMem != MAP_FAILED) {
7753013Syokota    VGLClear(VGLDisplay, 0);
7853013Syokota    munmap(VGLMem, VGLAdpInfo.va_window_size);
7950483Syokota  }
8053013Syokota
8150141Syokota  if (VGLOldMode >= M_VESA_BASE) {
8250141Syokota    /* ugly, but necessary */
8350141Syokota    ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0);
8450141Syokota    if (VGLOldMode == M_VESA_800x600) {
8550141Syokota      int size[3];
8676852Ssobomax      size[0] = VGLOldVInfo.mv_csz;
8776852Ssobomax      size[1] = VGLOldVInfo.mv_rsz;
8850141Syokota      size[2] = 16;
8950141Syokota      ioctl(0, KDRASTER, size);
9050141Syokota    }
9150141Syokota  } else {
9250141Syokota    ioctl(0, _IO('S', VGLOldMode), 0);
9350141Syokota  }
9428328Ssos  ioctl(0, KDDISABIO, 0);
9528328Ssos  ioctl(0, KDSETMODE, KD_TEXT);
9628328Ssos  smode.mode = VT_AUTO;
9728328Ssos  ioctl(0, VT_SETMODE, &smode);
9853013Syokota  if (VGLBuf)
9953013Syokota    free(VGLBuf);
10053013Syokota  VGLBuf = NULL;
10128328Ssos  free(VGLDisplay);
10253013Syokota  VGLDisplay = NULL;
10330044Ssos  VGLKeyboardEnd();
10428328Ssos}
10528328Ssos
10628328Ssosstatic void
10728328SsosVGLAbort()
10828328Ssos{
10980270Syokota  VGLAbortPending = 1;
11080270Syokota  signal(SIGINT, SIG_IGN);
11180270Syokota  signal(SIGTERM, SIG_IGN);
11280270Syokota  signal(SIGSEGV, SIG_IGN);
11380270Syokota  signal(SIGBUS, SIG_IGN);
11480270Syokota  signal(SIGUSR2, SIG_IGN);
11528328Ssos}
11628328Ssos
11728328Ssosstatic void
11828328SsosVGLSwitch()
11928328Ssos{
12028328Ssos  if (!VGLOnDisplay)
12128328Ssos    VGLOnDisplay = 1;
12228328Ssos  else
12328328Ssos    VGLOnDisplay = 0;
12428328Ssos  VGLSwitchPending = 1;
12528328Ssos  signal(SIGUSR1, VGLSwitch);
12628328Ssos}
12728328Ssos
12828328Ssosint
12928328SsosVGLInit(int mode)
13028328Ssos{
13128328Ssos  struct vt_mode smode;
13253013Syokota  int adptype;
13328328Ssos
13453013Syokota  if (VGLInitDone)
13553013Syokota    return -1;
13653013Syokota
13728328Ssos  signal(SIGUSR1, VGLSwitch);
13828328Ssos  signal(SIGINT, VGLAbort);
13950483Syokota  signal(SIGTERM, VGLAbort);
14028328Ssos  signal(SIGSEGV, VGLAbort);
14128328Ssos  signal(SIGBUS, VGLAbort);
14280270Syokota  signal(SIGUSR2, SIG_IGN);
14328328Ssos
14428328Ssos  VGLOnDisplay = 1;
14528328Ssos  VGLSwitchPending = 0;
14680270Syokota  VGLAbortPending = 0;
14728328Ssos
14853013Syokota  if (ioctl(0, CONS_GET, &VGLOldMode) || ioctl(0, CONS_CURRENT, &adptype))
14953013Syokota    return -1;
15053013Syokota  if (IOCGROUP(mode) == 'V')	/* XXX: this is ugly */
15153013Syokota    VGLModeInfo.vi_mode = (mode & 0x0ff) + M_VESA_BASE;
15253013Syokota  else
15353013Syokota    VGLModeInfo.vi_mode = mode & 0x0ff;
15453013Syokota  if (ioctl(0, CONS_MODEINFO, &VGLModeInfo))	/* FBIO_MODEINFO */
15553013Syokota    return -1;
15628328Ssos
15771643Ssobomax  /* If current mode is VESA_800x600 then save its geometry to restore later */
15876852Ssobomax  if ((VGLOldMode >= M_VESA_BASE) && (VGLOldMode == M_VESA_800x600)) {
15976852Ssobomax    VGLOldVInfo.size = sizeof(VGLOldVInfo);
16076852Ssobomax    if (ioctl(0, CONS_GETINFO, &VGLOldVInfo))
16171643Ssobomax      return -1;
16276852Ssobomax  }
16371643Ssobomax
16453013Syokota  VGLDisplay = (VGLBitmap *)malloc(sizeof(VGLBitmap));
16553013Syokota  if (VGLDisplay == NULL)
16653013Syokota    return -2;
16728328Ssos
16853013Syokota  if (ioctl(0, KDENABIO, 0)) {
16953013Syokota    free(VGLDisplay);
17053013Syokota    return -3;
17128328Ssos  }
17228328Ssos
17353013Syokota  VGLInitDone = 1;
17453013Syokota
17553013Syokota  /*
17653013Syokota   * vi_mem_model specifies the memory model of the current video mode
17753013Syokota   * in -CURRENT.
17853013Syokota   */
17953013Syokota  switch (VGLModeInfo.vi_mem_model) {
18053013Syokota  case V_INFO_MM_PLANAR:
18153013Syokota    /* we can handle EGA/VGA planner modes only */
18253013Syokota    if (VGLModeInfo.vi_depth != 4 || VGLModeInfo.vi_planes != 4
18353013Syokota	|| (adptype != KD_EGA && adptype != KD_VGA)) {
18453013Syokota      VGLEnd();
18553013Syokota      return -4;
18653013Syokota    }
18728328Ssos    VGLDisplay->Type = VIDBUF4;
18828328Ssos    break;
18953013Syokota  case V_INFO_MM_PACKED:
19053013Syokota    /* we can do only 256 color packed modes */
19153013Syokota    if (VGLModeInfo.vi_depth != 8) {
19253013Syokota      VGLEnd();
19353013Syokota      return -4;
19453013Syokota    }
19528328Ssos    VGLDisplay->Type = VIDBUF8;
19671623Snsouch    VGLDisplay->PixelBytes = 1;
19728328Ssos    break;
19853013Syokota  case V_INFO_MM_VGAX:
19928328Ssos    VGLDisplay->Type = VIDBUF8X;
20071623Snsouch    VGLDisplay->PixelBytes = 1;
20128328Ssos    break;
20270991Snsouch  case V_INFO_MM_DIRECT:
20370991Snsouch    VGLDisplay->PixelBytes = VGLModeInfo.vi_pixel_size;
20470991Snsouch    switch (VGLDisplay->PixelBytes) {
20570991Snsouch    case 2:
20670991Snsouch      VGLDisplay->Type = VIDBUF16;
20770991Snsouch      break;
20870991Snsouch#if notyet
20970991Snsouch    case 3:
21070991Snsouch      VGLDisplay->Type = VIDBUF24;
21170991Snsouch      break;
21270991Snsouch#endif
21370991Snsouch    case 4:
21470991Snsouch      VGLDisplay->Type = VIDBUF32;
21570991Snsouch      break;
21670991Snsouch    default:
21770991Snsouch      VGLEnd();
21870991Snsouch      return -4;
21970991Snsouch    }
22070991Snsouch    break;
22128328Ssos  default:
22228328Ssos    VGLEnd();
22353013Syokota    return -4;
22428328Ssos  }
22528328Ssos
22628328Ssos  ioctl(0, VT_WAITACTIVE, 0);
22728328Ssos  ioctl(0, KDSETMODE, KD_GRAPHICS);
22853013Syokota  if (ioctl(0, mode, 0)) {
22953013Syokota    VGLEnd();
23053013Syokota    return -5;
23128328Ssos  }
23253013Syokota  if (ioctl(0, CONS_ADPINFO, &VGLAdpInfo)) {	/* FBIO_ADPINFO */
23353013Syokota    VGLEnd();
23453013Syokota    return -6;
23553013Syokota  }
23628328Ssos
23753013Syokota  /*
23853013Syokota   * Calculate the shadow screen buffer size.  In -CURRENT, va_buffer_size
23953013Syokota   * always holds the entire frame buffer size, wheather it's in the linear
24053013Syokota   * mode or windowed mode.
24153013Syokota   *     VGLBufSize = VGLAdpInfo.va_buffer_size;
24253013Syokota   * In -STABLE, va_buffer_size holds the frame buffer size, only if
24353013Syokota   * the linear frame buffer mode is supported. Otherwise the field is zero.
24453013Syokota   * We shall calculate the minimal size in this case:
24553013Syokota   *     VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*VGLModeInfo.vi_planes
24653013Syokota   * or
24753013Syokota   *     VGLAdpInfo.va_window_size*VGLModeInfo.vi_planes;
24853013Syokota   * Use whichever is larger.
24953013Syokota   */
25053013Syokota  if (VGLAdpInfo.va_buffer_size != 0)
25153013Syokota    VGLBufSize = VGLAdpInfo.va_buffer_size;
25253013Syokota  else
25353013Syokota    VGLBufSize = max(VGLAdpInfo.va_line_width*VGLModeInfo.vi_height,
25453013Syokota		     VGLAdpInfo.va_window_size)*VGLModeInfo.vi_planes;
25553013Syokota  VGLBuf = malloc(VGLBufSize);
25653013Syokota  if (VGLBuf == NULL) {
25753013Syokota    VGLEnd();
25853013Syokota    return -7;
25953013Syokota  }
26053013Syokota
26153013Syokota#ifdef LIBVGL_DEBUG
26253013Syokota  fprintf(stderr, "VGLBufSize:0x%x\n", VGLBufSize);
26353013Syokota#endif
26453013Syokota
26553013Syokota  /* see if we are in the windowed buffer mode or in the linear buffer mode */
26653013Syokota  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size) {
26770991Snsouch    switch (VGLDisplay->Type) {
26870991Snsouch    case VIDBUF4:
26953013Syokota      VGLDisplay->Type = VIDBUF4S;
27070991Snsouch      break;
27170991Snsouch    case VIDBUF8:
27253013Syokota      VGLDisplay->Type = VIDBUF8S;
27370991Snsouch      break;
27470991Snsouch    case VIDBUF16:
27570991Snsouch      VGLDisplay->Type = VIDBUF16S;
27670991Snsouch      break;
27770991Snsouch    case VIDBUF24:
27870991Snsouch      VGLDisplay->Type = VIDBUF24S;
27970991Snsouch      break;
28070991Snsouch    case VIDBUF32:
28170991Snsouch      VGLDisplay->Type = VIDBUF32S;
28270991Snsouch      break;
28370991Snsouch    default:
28470991Snsouch      VGLEnd();
28570991Snsouch      return -8;
28670991Snsouch    }
28753013Syokota  }
28853013Syokota
28928328Ssos  VGLMode = mode;
29053013Syokota  VGLCurWindow = 0;
29128328Ssos
29253013Syokota  VGLDisplay->Xsize = VGLModeInfo.vi_width;
29353013Syokota  VGLDisplay->Ysize = VGLModeInfo.vi_height;
29453013Syokota  VGLDisplay->VXsize = VGLAdpInfo.va_line_width
29553013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
29653013Syokota  VGLDisplay->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
29753013Syokota  VGLDisplay->Xorigin = 0;
29853013Syokota  VGLDisplay->Yorigin = 0;
29928328Ssos
30053013Syokota  VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
30153013Syokota		       MAP_FILE, 0, 0);
30253013Syokota  if (VGLMem == MAP_FAILED) {
30328328Ssos    VGLEnd();
30453013Syokota    return -7;
30528328Ssos  }
30653013Syokota  VGLDisplay->Bitmap = VGLMem;
30728328Ssos
30828328Ssos  VGLSavePalette();
30928328Ssos
31053013Syokota#ifdef LIBVGL_DEBUG
31153013Syokota  fprintf(stderr, "va_line_width:%d\n", VGLAdpInfo.va_line_width);
31253013Syokota  fprintf(stderr, "VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
31353013Syokota	  VGLDisplay->Xsize, VGLDisplay->Ysize,
31453013Syokota	  VGLDisplay->VXsize, VGLDisplay->VYsize);
31553013Syokota#endif
31653013Syokota
31728328Ssos  smode.mode = VT_PROCESS;
31828328Ssos  smode.waitv = 0;
31928328Ssos  smode.relsig = SIGUSR1;
32028328Ssos  smode.acqsig = SIGUSR1;
32128328Ssos  smode.frsig  = SIGINT;
32253013Syokota  if (ioctl(0, VT_SETMODE, &smode)) {
32328328Ssos    VGLEnd();
32453013Syokota    return -9;
32528328Ssos  }
32628328Ssos  VGLTextSetFontFile((byte*)0);
32753013Syokota  VGLClear(VGLDisplay, 0);
32828328Ssos  return 0;
32928328Ssos}
33028328Ssos
33128328Ssosvoid
33228328SsosVGLCheckSwitch()
33328328Ssos{
33480270Syokota  if (VGLAbortPending) {
33580270Syokota    VGLEnd();
33680270Syokota    exit(0);
33780270Syokota  }
33850483Syokota  while (VGLSwitchPending) {
33953013Syokota    unsigned int offset;
34053013Syokota    unsigned int len;
34128328Ssos    int i;
34228328Ssos
34328328Ssos    VGLSwitchPending = 0;
34428328Ssos    if (VGLOnDisplay) {
34528328Ssos      ioctl(0, KDENABIO, 0);
34628328Ssos      ioctl(0, KDSETMODE, KD_GRAPHICS);
34728328Ssos      ioctl(0, VGLMode, 0);
34853013Syokota      VGLCurWindow = 0;
34953013Syokota      VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
35053013Syokota			   MAP_FILE, 0, 0);
35153013Syokota
35253013Syokota      /* XXX: what if mmap() has failed! */
35353013Syokota      VGLDisplay->Type = VIDBUF8;	/* XXX */
35453013Syokota      switch (VGLModeInfo.vi_mem_model) {
35553013Syokota      case V_INFO_MM_PLANAR:
35653013Syokota	if (VGLModeInfo.vi_depth == 4 && VGLModeInfo.vi_planes == 4) {
35753013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
35853013Syokota	    VGLDisplay->Type = VIDBUF4S;
35953013Syokota	  else
36053013Syokota	    VGLDisplay->Type = VIDBUF4;
36153013Syokota	} else {
36253013Syokota	  /* shouldn't be happening */
36353013Syokota	}
36428328Ssos        break;
36553013Syokota      case V_INFO_MM_PACKED:
36653013Syokota	if (VGLModeInfo.vi_depth == 8) {
36753013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
36853013Syokota	    VGLDisplay->Type = VIDBUF8S;
36953013Syokota	  else
37053013Syokota	    VGLDisplay->Type = VIDBUF8;
37153013Syokota	}
37228328Ssos        break;
37353013Syokota      case V_INFO_MM_VGAX:
37453013Syokota	VGLDisplay->Type = VIDBUF8X;
37553013Syokota	break;
37670991Snsouch      case V_INFO_MM_DIRECT:
37770991Snsouch	switch (VGLModeInfo.vi_pixel_size) {
37870991Snsouch	  case 2:
37970991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
38070991Snsouch	      VGLDisplay->Type = VIDBUF16S;
38170991Snsouch	    else
38270991Snsouch	      VGLDisplay->Type = VIDBUF16;
38370991Snsouch	    break;
38470991Snsouch	  case 3:
38570991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
38670991Snsouch	      VGLDisplay->Type = VIDBUF24S;
38770991Snsouch	    else
38870991Snsouch	      VGLDisplay->Type = VIDBUF24;
38970991Snsouch	    break;
39070991Snsouch	  case 4:
39170991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
39270991Snsouch	      VGLDisplay->Type = VIDBUF32S;
39370991Snsouch	    else
39470991Snsouch	      VGLDisplay->Type = VIDBUF32;
39570991Snsouch	    break;
39670991Snsouch	  default:
39770991Snsouch	  /* shouldn't be happening */
39870991Snsouch          break;
39970991Snsouch        }
40028328Ssos      default:
40153013Syokota	/* shouldn't be happening */
40228328Ssos        break;
40328328Ssos      }
40453013Syokota
40553013Syokota      VGLDisplay->Bitmap = VGLMem;
40653013Syokota      VGLDisplay->Xsize = VGLModeInfo.vi_width;
40753013Syokota      VGLDisplay->Ysize = VGLModeInfo.vi_height;
40853013Syokota      VGLSetVScreenSize(VGLDisplay, VGLDisplay->VXsize, VGLDisplay->VYsize);
40953013Syokota      VGLPanScreen(VGLDisplay, VGLDisplay->Xorigin, VGLDisplay->Yorigin);
41053013Syokota      switch (VGLDisplay->Type) {
41153013Syokota      case VIDBUF4S:
41253013Syokota	outb(0x3c6, 0xff);
41353013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
41453013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
41553013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
41653013Syokota	     offset += len) {
41753013Syokota	  VGLSetSegment(offset);
41853013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
41953013Syokota		    VGLAdpInfo.va_window_size);
42053013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
42153013Syokota	    outb(0x3c4, 0x02);
42253013Syokota	    outb(0x3c5, 0x01<<i);
42353013Syokota	    bcopy(&VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
42453013Syokota		  VGLMem, len);
42553013Syokota	  }
42653013Syokota	}
42753013Syokota	break;
42853013Syokota      case VIDBUF4:
42953013Syokota      case VIDBUF8X:
43053013Syokota	outb(0x3c6, 0xff);
43153013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
43253013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
43353013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
43453013Syokota	  outb(0x3c4, 0x02);
43553013Syokota	  outb(0x3c5, 0x01<<i);
43653013Syokota	  bcopy(&VGLBuf[i*VGLAdpInfo.va_window_size], VGLMem,
43753013Syokota		VGLAdpInfo.va_window_size);
43853013Syokota	}
43953013Syokota	break;
44053013Syokota      case VIDBUF8:
44153013Syokota      case VIDBUF8S:
44270991Snsouch      case VIDBUF16:
44370991Snsouch      case VIDBUF16S:
44470991Snsouch      case VIDBUF24:
44570991Snsouch      case VIDBUF24S:
44670991Snsouch      case VIDBUF32:
44770991Snsouch      case VIDBUF32S:
44853013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
44953013Syokota	  VGLSetSegment(offset);
45053013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
45153013Syokota          bcopy(&VGLBuf[offset], VGLMem, len);
45253013Syokota	}
45353013Syokota	break;
45453013Syokota      }
45553013Syokota      VGLRestorePalette();
45653013Syokota      ioctl(0, VT_RELDISP, VT_ACKACQ);
45728328Ssos    }
45828328Ssos    else {
45953013Syokota      switch (VGLDisplay->Type) {
46053013Syokota      case VIDBUF4S:
46153013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
46253013Syokota	     offset += len) {
46353013Syokota	  VGLSetSegment(offset);
46453013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
46553013Syokota		    VGLAdpInfo.va_window_size);
46653013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
46753013Syokota	    outb(0x3ce, 0x04);
46853013Syokota	    outb(0x3cf, i);
46953013Syokota	    bcopy(VGLMem, &VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
47053013Syokota		  len);
47153013Syokota	  }
47253013Syokota	}
47353013Syokota	break;
47453013Syokota      case VIDBUF4:
47553013Syokota      case VIDBUF8X:
47653013Syokota	/*
47753013Syokota	 * NOTE: the saved buffer is NOT in the MEMBUF format which
47853013Syokota	 * the ordinary memory bitmap object is stored in. XXX
47953013Syokota	 */
48053013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
48153013Syokota	  outb(0x3ce, 0x04);
48253013Syokota	  outb(0x3cf, i);
48353013Syokota	  bcopy(VGLMem, &VGLBuf[i*VGLAdpInfo.va_window_size],
48453013Syokota		VGLAdpInfo.va_window_size);
48553013Syokota	}
48653013Syokota	break;
48753013Syokota      case VIDBUF8:
48853013Syokota      case VIDBUF8S:
48970991Snsouch      case VIDBUF16:
49070991Snsouch      case VIDBUF16S:
49170991Snsouch      case VIDBUF24:
49270991Snsouch      case VIDBUF24S:
49370991Snsouch      case VIDBUF32:
49470991Snsouch      case VIDBUF32S:
49553013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
49653013Syokota	  VGLSetSegment(offset);
49753013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
49853013Syokota          bcopy(VGLMem, &VGLBuf[offset], len);
49953013Syokota	}
50053013Syokota	break;
50128328Ssos      }
50253013Syokota      VGLMem = MAP_FAILED;
50353013Syokota      munmap(VGLDisplay->Bitmap, VGLAdpInfo.va_window_size);
50428328Ssos      ioctl(0, VGLOldMode, 0);
50528328Ssos      ioctl(0, KDSETMODE, KD_TEXT);
50628328Ssos      ioctl(0, KDDISABIO, 0);
50728328Ssos      ioctl(0, VT_RELDISP, VT_TRUE);
50828328Ssos      VGLDisplay->Bitmap = VGLBuf;
50928328Ssos      VGLDisplay->Type = MEMBUF;
51053013Syokota      VGLDisplay->Xsize = VGLDisplay->VXsize;
51153013Syokota      VGLDisplay->Ysize = VGLDisplay->VYsize;
51250483Syokota      while (!VGLOnDisplay) pause();
51328328Ssos    }
51428328Ssos  }
51528328Ssos}
51653013Syokota
51753013Syokotaint
51853013SyokotaVGLSetSegment(unsigned int offset)
51953013Syokota{
52053013Syokota  if (offset/VGLAdpInfo.va_window_size != VGLCurWindow) {
52153013Syokota    ioctl(0, CONS_SETWINORG, offset);		/* FBIO_SETWINORG */
52253013Syokota    VGLCurWindow = offset/VGLAdpInfo.va_window_size;
52353013Syokota  }
52453013Syokota  return (offset%VGLAdpInfo.va_window_size);
52553013Syokota}
52653013Syokota
52753013Syokotaint
52853013SyokotaVGLSetVScreenSize(VGLBitmap *object, int VXsize, int VYsize)
52953013Syokota{
53053013Syokota  if (VXsize < object->Xsize || VYsize < object->Ysize)
53153013Syokota    return -1;
53253013Syokota  if (object->Type == MEMBUF)
53353013Syokota    return -1;
53453013Syokota  if (ioctl(0, FBIO_SETLINEWIDTH, &VXsize))
53553013Syokota    return -1;
53653013Syokota  ioctl(0, CONS_ADPINFO, &VGLAdpInfo);	/* FBIO_ADPINFO */
53753013Syokota  object->VXsize = VGLAdpInfo.va_line_width
53853013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
53953013Syokota  object->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
54053013Syokota  if (VYsize < object->VYsize)
54153013Syokota    object->VYsize = VYsize;
54253013Syokota
54353013Syokota#ifdef LIBVGL_DEBUG
54453013Syokota  fprintf(stderr, "new size: VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
54553013Syokota	  object->Xsize, object->Ysize, object->VXsize, object->VYsize);
54653013Syokota#endif
54753013Syokota
54853013Syokota  return 0;
54953013Syokota}
55053013Syokota
55153013Syokotaint
55253013SyokotaVGLPanScreen(VGLBitmap *object, int x, int y)
55353013Syokota{
55453013Syokota  video_display_start_t origin;
55553013Syokota
55653013Syokota  if (x < 0 || x + object->Xsize > object->VXsize
55753013Syokota      || y < 0 || y + object->Ysize > object->VYsize)
55853013Syokota    return -1;
55953013Syokota  if (object->Type == MEMBUF)
56053013Syokota    return 0;
56153013Syokota  origin.x = x;
56253013Syokota  origin.y = y;
56353013Syokota  if (ioctl(0, FBIO_SETDISPSTART, &origin))
56453013Syokota    return -1;
56553013Syokota  object->Xorigin = x;
56653013Syokota  object->Yorigin = y;
56753013Syokota
56853013Syokota#ifdef LIBVGL_DEBUG
56953013Syokota  fprintf(stderr, "new origin: (%d, %d)\n", x, y);
57053013Syokota#endif
57153013Syokota
57253013Syokota  return 0;
57353013Syokota}
574