bitmap.c revision 50141
1185377Ssam/*-
2185377Ssam * Copyright (c) 1991-1997 S�ren Schmidt
3185377Ssam * All rights reserved.
4185377Ssam *
5185377Ssam * Redistribution and use in source and binary forms, with or without
6185377Ssam * modification, are permitted provided that the following conditions
7185377Ssam * are met:
8185377Ssam * 1. Redistributions of source code must retain the above copyright
9185377Ssam *    notice, this list of conditions and the following disclaimer,
10185377Ssam *    in this position and unchanged.
11185377Ssam * 2. Redistributions in binary form must reproduce the above copyright
12185377Ssam *    notice, this list of conditions and the following disclaimer in the
13185377Ssam *    documentation and/or other materials provided with the distribution.
14185377Ssam * 3. The name of the author may not be used to endorse or promote products
15185377Ssam *    derived from this software withough specific prior written permission.
16185377Ssam *
17185377Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18185377Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19185377Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20185377Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21185377Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22185377Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23185377Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24185377Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25185377Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26185377Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27185377Ssam *
28185377Ssam *  $Id: bitmap.c,v 1.1 1997/08/17 21:09:34 sos Exp $
29185377Ssam */
30185377Ssam
31185377Ssam#include <sys/types.h>
32185377Ssam#include <signal.h>
33185377Ssam#include "vgl.h"
34185377Ssam
35185377Ssamstatic byte VGLPlane[4][128];
36185377Ssamstatic byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
37185377Ssamstatic int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101,
38185377Ssam			    0x00010000, 0x00010001, 0x00010100, 0x00010101,
39185377Ssam			    0x01000000, 0x01000001, 0x01000100, 0x01000101,
40185377Ssam			    0x01010000, 0x01010001, 0x01010100, 0x01010101};
41185377Ssam
42185377Ssamstatic void
43185377SsamWriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line)
44185377Ssam{
45185377Ssam  int i, pos, last, planepos, start_offset, end_offset, offset;
46185377Ssam  unsigned int word = 0;
47185377Ssam  byte *address;
48185377Ssam
49185377Ssam  switch (dst->Type) {
50185377Ssam  case VIDBUF4:
51185377Ssam    address = dst->Bitmap + (dst->Xsize/8 * y) + x/8;
52185377Ssam    start_offset = (x & 0x07);
53185377Ssam    end_offset = (x + width) & 0x07;
54185377Ssam    offset = start_offset;
55185377Ssam    pos = 0;
56185377Ssam    planepos = 0;
57185377Ssam    while (pos < width) {
58185377Ssam      word = 0;
59185377Ssam      last = pos + 8 - offset;
60185377Ssam      while (pos < last && pos < width)
61185377Ssam	word = (word<<1) | color2bit[line[pos++]&0x0f];
62185377Ssam      VGLPlane[0][planepos] = word;
63185377Ssam      VGLPlane[1][planepos] = word>>8;
64185377Ssam      VGLPlane[2][planepos] = word>>16;
65185377Ssam      VGLPlane[3][planepos] = word>>24;
66185377Ssam      planepos++;
67185377Ssam      offset = 0;
68185377Ssam    }
69185377Ssam    planepos--;
70185377Ssam    if (end_offset) {
71185377Ssam      word <<= (8 - end_offset);
72185377Ssam      VGLPlane[0][planepos] = word;
73185377Ssam      VGLPlane[1][planepos] = word>>8;
74185377Ssam      VGLPlane[2][planepos] = word>>16;
75185377Ssam      VGLPlane[3][planepos] = word>>24;
76185377Ssam    }
77185377Ssam    if (start_offset || end_offset)
78185377Ssam      width+=8;
79185377Ssam    for (i=0; i<4; i++) {
80185377Ssam      outb(0x3c4, 0x02);
81185377Ssam      outb(0x3c5, 0x01<<i);
82185377Ssam      outb(0x3ce, 0x04);
83185377Ssam      outb(0x3cf, i);
84185377Ssam      if (start_offset)
85185377Ssam	VGLPlane[i][0] |= *address & ~mask[start_offset];
86185377Ssam      if (end_offset)
87185377Ssam	VGLPlane[i][planepos] |= *(address + planepos) & mask[end_offset];
88185377Ssam      bcopy(&VGLPlane[i][0], address, width/8);
89185377Ssam    }
90185377Ssam    break;
91185377Ssam  case VIDBUF8X:
92185377Ssam    address = dst->Bitmap + (dst->Xsize/2 * y) + x/4;
93185377Ssam    for (i=0; i<4; i++) {
94185377Ssam      outb(0x3c4, 0x02);
95185377Ssam      outb(0x3c5, 0x01 << ((x + i)%4));
96185377Ssam      for (planepos=0, pos=i; pos<width; planepos++, pos+=4)
97185377Ssam        address[planepos] = line[pos];
98185377Ssam      if ((x + i)%4 == 3)
99185377Ssam	++address;
100185377Ssam    }
101185377Ssam    break;
102185377Ssam  case VIDBUF8:
103185377Ssam  case MEMBUF:
104185377Ssam    address = dst->Bitmap + (dst->Xsize * y) + x;
105185377Ssam    bcopy(line, address, width);
106185377Ssam    break;
107185377Ssam
108185377Ssam  default:
109185377Ssam  }
110185377Ssam}
111185377Ssam
112185377Ssamstatic void
113185377SsamReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line)
114185377Ssam{
115185377Ssam  int i, bit, pos, count, planepos, start_offset, end_offset, offset;
116185377Ssam  byte *address;
117185377Ssam
118185377Ssam  switch (src->Type) {
119185377Ssam  case VIDBUF4:
120185377Ssam    address = src->Bitmap + (src->Xsize/8 * y) + x/8;
121185377Ssam    start_offset = (x & 0x07);
122185377Ssam    end_offset = (x + width) & 0x07;
123185377Ssam    offset = start_offset;
124185377Ssam    if (start_offset)
125185377Ssam	count = (width - (8 - start_offset)) / 8 + 1;
126185377Ssam    else
127185377Ssam	count = width / 8;
128185377Ssam    if (end_offset)
129185377Ssam	count++;
130185377Ssam    for (i=0; i<4; i++) {
131185377Ssam      outb(0x3ce, 0x04);
132185377Ssam      outb(0x3cf, i);
133185377Ssam      bcopy(address, &VGLPlane[i][0], count);
134185377Ssam    }
135185377Ssam    pos = 0;
136185377Ssam    planepos = 0;
137185377Ssam    while (pos < width) {
138185377Ssam      for (bit = (7-offset); bit >= 0 && pos < width; bit--, pos++) {
139185377Ssam        line[pos] = (VGLPlane[0][planepos] & (1<<bit) ? 1 : 0) |
140185377Ssam                    ((VGLPlane[1][planepos] & (1<<bit) ? 1 : 0) << 1) |
141185377Ssam                    ((VGLPlane[2][planepos] & (1<<bit) ? 1 : 0) << 2) |
142185377Ssam                    ((VGLPlane[3][planepos] & (1<<bit) ? 1 : 0) << 3);
143185377Ssam      }
144185377Ssam      planepos++;
145185377Ssam      offset = 0;
146185377Ssam    }
147185377Ssam    break;
148185377Ssam  case VIDBUF8X:
149185377Ssam    address = src->Bitmap + (src->Xsize/2 * y) + x/4;
150185377Ssam    for (i=0; i<4; i++) {
151185377Ssam      outb(0x3ce, 0x04);
152185377Ssam      outb(0x3cf, (x + i)%4);
153185377Ssam      for (planepos=0, pos=i; pos<width; planepos++, pos+=4)
154185377Ssam        line[pos] = address[planepos];
155185377Ssam      if ((x + i)%4 == 3)
156185377Ssam	++address;
157185377Ssam    }
158185377Ssam    break;
159185377Ssam  case VIDBUF8:
160185377Ssam  case MEMBUF:
161185377Ssam    address = src->Bitmap + (src->Xsize * y) + x;
162185377Ssam    bcopy(address, line, width);
163185377Ssam    break;
164185377Ssam  default:
165185377Ssam  }
166185377Ssam}
167185377Ssam
168185377Ssamint
169185377Ssam__VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
170185377Ssam	      VGLBitmap *dst, int dstx, int dsty, int width, int hight)
171185377Ssam{
172185377Ssam  int srcline, dstline;
173185377Ssam
174185377Ssam  if (srcx>src->Xsize||srcy>src->Ysize||dstx>dst->Xsize||dsty>dst->Ysize)
175185377Ssam    return -1;
176185377Ssam  if (srcx < 0) {
177185377Ssam    width=width+srcx; dstx-=srcx; srcx=0;
178185377Ssam  }
179185377Ssam  if (srcy < 0) {
180185377Ssam    hight=hight+srcy; dsty-=srcy; srcy=0;
181185377Ssam  }
182185377Ssam  if (dstx < 0) {
183185377Ssam    width=width+dstx; srcx-=dstx; dstx=0;
184185377Ssam  }
185185377Ssam  if (dsty < 0) {
186185377Ssam    hight=hight+dsty; srcy-=dsty; dsty=0;
187185377Ssam  }
188185377Ssam  if (srcx+width > src->Xsize)
189185377Ssam     width=src->Xsize-srcx;
190185377Ssam  if (srcy+hight > src->Ysize)
191185377Ssam     hight=src->Ysize-srcy;
192185377Ssam  if (dstx+width > dst->Xsize)
193185377Ssam     width=dst->Xsize-dstx;
194185377Ssam  if (dsty+hight > dst->Ysize)
195185377Ssam     hight=dst->Ysize-dsty;
196185377Ssam  if (width < 0 || hight < 0)
197185377Ssam     return -1;
198185377Ssam  if (src->Type == MEMBUF) {
199185377Ssam    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
200185377Ssam      WriteVerticalLine(dst, dstx, dstline, width,
201185377Ssam	(src->Bitmap+(srcline*src->Xsize)+srcx));
202185377Ssam    }
203185377Ssam  }
204185377Ssam  else if (dst->Type == MEMBUF) {
205185377Ssam    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
206185377Ssam      ReadVerticalLine(src, srcx, srcline, width,
207185377Ssam	 (dst->Bitmap+(dstline*dst->Xsize)+dstx));
208185377Ssam    }
209185377Ssam  }
210185377Ssam  else {
211185377Ssam    byte buffer[1024];
212185377Ssam    for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
213185377Ssam      ReadVerticalLine(src, srcx, srcline, width, buffer);
214185377Ssam      WriteVerticalLine(dst, dstx, dstline, width, buffer);
215185377Ssam    }
216185377Ssam  }
217185377Ssam  return 0;
218185377Ssam}
219185377Ssam
220185377Ssamint
221185377SsamVGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
222185377Ssam	      VGLBitmap *dst, int dstx, int dsty, int width, int hight)
223185377Ssam{
224185377Ssam  int error;
225185377Ssam
226185377Ssam  VGLMouseFreeze(dstx, dsty, width, hight, 0);
227185377Ssam  error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
228185377Ssam  VGLMouseUnFreeze();
229185377Ssam  return error;
230185377Ssam}
231185377Ssam
232185377Ssam