bitmap.c revision 28328
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 *
2828328Ssos *  $Id: bitmap.c,v 1.8 1997/08/15 12:32:59 sos Exp $
2928328Ssos */
3028328Ssos
3128328Ssos#include <sys/types.h>
3228328Ssos#include <signal.h>
3328328Ssos#include "vgl.h"
3428328Ssos
3528328Ssosstatic byte VGLPlane[4][128];
3628328Ssosstatic byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
3728328Ssosstatic int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101,
3828328Ssos			    0x00010000, 0x00010001, 0x00010100, 0x00010101,
3928328Ssos			    0x01000000, 0x01000001, 0x01000100, 0x01000101,
4028328Ssos			    0x01010000, 0x01010001, 0x01010100, 0x01010101};
4128328Ssos
4228328Ssosstatic void
4328328SsosWriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line)
4428328Ssos{
4528328Ssos  int i, pos, last, planepos, start_offset, end_offset, offset;
4628328Ssos  unsigned int word = 0;
4728328Ssos  byte *address;
4828328Ssos
4928328Ssos  switch (dst->Type) {
5028328Ssos  case VIDBUF4:
5128328Ssos    address = dst->Bitmap + (dst->Xsize/8 * y) + x/8;
5228328Ssos    start_offset = (x & 0x07);
5328328Ssos    end_offset = (x + width) & 0x07;
5428328Ssos    offset = start_offset;
5528328Ssos    pos = 0;
5628328Ssos    planepos = 0;
5728328Ssos    while (pos < width) {
5828328Ssos      word = 0;
5928328Ssos      last = pos + 8 - offset;
6028328Ssos      while (pos < last && pos < width)
6128328Ssos	word = (word<<1) | color2bit[line[pos++]&0x0f];
6228328Ssos      VGLPlane[0][planepos] = word;
6328328Ssos      VGLPlane[1][planepos] = word>>8;
6428328Ssos      VGLPlane[2][planepos] = word>>16;
6528328Ssos      VGLPlane[3][planepos] = word>>24;
6628328Ssos      planepos++;
6728328Ssos      offset = 0;
6828328Ssos    }
6928328Ssos    planepos--;
7028328Ssos    if (end_offset) {
7128328Ssos      word <<= (8 - end_offset);
7228328Ssos      VGLPlane[0][planepos] = word;
7328328Ssos      VGLPlane[1][planepos] = word>>8;
7428328Ssos      VGLPlane[2][planepos] = word>>16;
7528328Ssos      VGLPlane[3][planepos] = word>>24;
7628328Ssos    }
7728328Ssos    if (start_offset || end_offset)
7828328Ssos      width+=8;
7928328Ssos    for (i=0; i<4; i++) {
8028328Ssos      outb(0x3c4, 0x02);
8128328Ssos      outb(0x3c5, 0x01<<i);
8228328Ssos      outb(0x3ce, 0x04);
8328328Ssos      outb(0x3cf, i);
8428328Ssos      if (start_offset)
8528328Ssos	VGLPlane[i][0] |= *address & ~mask[start_offset];
8628328Ssos      if (end_offset)
8728328Ssos	VGLPlane[i][planepos] |= *(address + planepos) & mask[end_offset];
8828328Ssos      bcopy(&VGLPlane[i][0], address, width/8);
8928328Ssos    }
9028328Ssos    break;
9128328Ssos  case VIDBUF8X:
9228328Ssos    address = dst->Bitmap + ((dst->Xsize * y) + x)/2;
9328328Ssos    for (i=0; i<4; i++) {
9428328Ssos      outb(0x3c4, 0x02);
9528328Ssos      outb(0x3c5, 0x01<<i);
9628328Ssos      pos = i;
9728328Ssos      for (planepos=0; planepos<width/4; planepos++, pos+=4)
9828328Ssos        address[planepos] = line[pos];
9928328Ssos    }
10028328Ssos    break;
10128328Ssos  case VIDBUF8:
10228328Ssos  case MEMBUF:
10328328Ssos    address = dst->Bitmap + (dst->Xsize * y) + x;
10428328Ssos    bcopy(line, address, width);
10528328Ssos    break;
10628328Ssos
10728328Ssos  default:
10828328Ssos  }
10928328Ssos}
11028328Ssos
11128328Ssosstatic void
11228328SsosReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line)
11328328Ssos{
11428328Ssos  int i, bit, pos, count, planepos, start_offset, end_offset, offset;
11528328Ssos  byte *address;
11628328Ssos
11728328Ssos  switch (src->Type) {
11828328Ssos  case VIDBUF4:
11928328Ssos    address = src->Bitmap + (src->Xsize/8 * y) + x/8;
12028328Ssos    start_offset = (x & 0x07);
12128328Ssos    end_offset = (x + width) & 0x07;
12228328Ssos    offset = start_offset;
12328328Ssos    if (start_offset)
12428328Ssos	count = (width - (8 - start_offset)) / 8 + 1;
12528328Ssos    else
12628328Ssos	count = width / 8;
12728328Ssos    if (end_offset)
12828328Ssos	count++;
12928328Ssos    for (i=0; i<4; i++) {
13028328Ssos      outb(0x3ce, 0x04);
13128328Ssos      outb(0x3cf, i);
13228328Ssos      bcopy(address, &VGLPlane[i][0], count);
13328328Ssos    }
13428328Ssos    pos = 0;
13528328Ssos    planepos = 0;
13628328Ssos    while (pos < width) {
13728328Ssos      for (bit = (7-offset); bit >= 0 && pos < width; bit--, pos++) {
13828328Ssos        line[pos] = (VGLPlane[0][planepos] & (1<<bit) ? 1 : 0) |
13928328Ssos                    ((VGLPlane[1][planepos] & (1<<bit) ? 1 : 0) << 1) |
14028328Ssos                    ((VGLPlane[2][planepos] & (1<<bit) ? 1 : 0) << 2) |
14128328Ssos                    ((VGLPlane[3][planepos] & (1<<bit) ? 1 : 0) << 3);
14228328Ssos      }
14328328Ssos      planepos++;
14428328Ssos      offset = 0;
14528328Ssos    }
14628328Ssos    break;
14728328Ssos  case VIDBUF8X:
14828328Ssos    address = src->Bitmap + ((src->Xsize * y) + x)/2;
14928328Ssos    for (i=0; i<4; i++) {
15028328Ssos      outb(0x3ce, 0x04);
15128328Ssos      outb(0x3cf, i);
15228328Ssos      pos = i;
15328328Ssos      for (planepos=0; planepos<width/4; planepos++, pos+=4)
15428328Ssos        line[pos] = address[planepos];
15528328Ssos    }
15628328Ssos    break;
15728328Ssos  case VIDBUF8:
15828328Ssos  case MEMBUF:
15928328Ssos    address = src->Bitmap + (src->Xsize * y) + x;
16028328Ssos    bcopy(address, line, width);
16128328Ssos    break;
16228328Ssos  default:
16328328Ssos  }
16428328Ssos}
16528328Ssos
16628328Ssosint
16728328Ssos__VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
16828328Ssos	      VGLBitmap *dst, int dstx, int dsty, int width, int hight)
16928328Ssos{
17028328Ssos  int srcline, dstline;
17128328Ssos
17228328Ssos  if (srcx>src->Xsize||srcy>src->Ysize||dsty>dst->Xsize||dsty>dst->Ysize)
17328328Ssos    return -1;
17428328Ssos  if (srcx < 0) {
17528328Ssos    width=width+srcx; dstx-=srcx; srcx=0;
17628328Ssos  }
17728328Ssos  if (srcy < 0) {
17828328Ssos    hight=hight+srcy; dsty-=srcy; srcy=0;
17928328Ssos  }
18028328Ssos  if (dstx < 0) {
18128328Ssos    width=width+dstx; srcx-=dstx; dstx=0;
18228328Ssos  }
18328328Ssos  if (dsty < 0) {
18428328Ssos    hight=hight+dsty; srcy-=dsty; dsty=0;
18528328Ssos  }
18628328Ssos  if (srcx+width > src->Xsize)
18728328Ssos     width=src->Xsize-srcx;
18828328Ssos  if (srcy+hight > src->Ysize)
18928328Ssos     hight=src->Ysize-srcy;
19028328Ssos  if (dstx+width > dst->Xsize)
19128328Ssos     width=dst->Xsize-dstx;
19228328Ssos  if (dsty+hight > dst->Ysize)
19328328Ssos     hight=dst->Ysize-dsty;
19428328Ssos  if (width < 0 || hight < 0)
19528328Ssos     return -1;
19628328Ssos  if (src->Type == MEMBUF) {
19728328Ssos    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
19828328Ssos      WriteVerticalLine(dst, dstx, dstline, width,
19928328Ssos	(src->Bitmap+(srcline*src->Xsize)+srcx));
20028328Ssos    }
20128328Ssos  }
20228328Ssos  else if (dst->Type == MEMBUF) {
20328328Ssos    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
20428328Ssos      ReadVerticalLine(src, srcx, srcline, width,
20528328Ssos	 (dst->Bitmap+(dstline*dst->Xsize)+dstx));
20628328Ssos    }
20728328Ssos  }
20828328Ssos  else {
20928328Ssos    byte buffer[1024];
21028328Ssos    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
21128328Ssos      ReadVerticalLine(src, srcx, srcline, width, buffer);
21228328Ssos      WriteVerticalLine(dst, dstx, dstline, width, buffer);
21328328Ssos    }
21428328Ssos  }
21528328Ssos  return 0;
21628328Ssos}
21728328Ssos
21828328Ssosint
21928328SsosVGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
22028328Ssos	      VGLBitmap *dst, int dstx, int dsty, int width, int hight)
22128328Ssos{
22228328Ssos  int error;
22328328Ssos
22428328Ssos  VGLMouseFreeze(dstx, dsty, width, hight, 0);
22528328Ssos  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
22628328Ssos  VGLMouseUnFreeze();
22728328Ssos  return error;
22828328Ssos}
22928328Ssos
230