]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libvgl/bitmap.c
This commit was generated by cvs2svn to compensate for changes in r80508,
[FreeBSD/FreeBSD.git] / lib / libvgl / bitmap.c
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$
29  */
30
31 #include <sys/types.h>
32 #include <signal.h>
33 #include <sys/fbio.h>
34 #include "vgl.h"
35
36 #define min(x, y)       (((x) < (y)) ? (x) : (y))
37
38 static byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
39 static int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101,
40                             0x00010000, 0x00010001, 0x00010100, 0x00010101,
41                             0x01000000, 0x01000001, 0x01000100, 0x01000101,
42                             0x01010000, 0x01010001, 0x01010100, 0x01010101};
43
44 static void
45 WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line)
46 {
47   int i, pos, last, planepos, start_offset, end_offset, offset;
48   int len;
49   unsigned int word = 0;
50   byte *address;
51   byte *VGLPlane[4];
52
53   switch (dst->Type) {
54   case VIDBUF4:
55   case VIDBUF4S:
56     start_offset = (x & 0x07);
57     end_offset = (x + width) & 0x07;
58     i = (width + start_offset) / 8;
59     if (end_offset)
60         i++;
61     VGLPlane[0] = VGLBuf;
62     VGLPlane[1] = VGLPlane[0] + i;
63     VGLPlane[2] = VGLPlane[1] + i;
64     VGLPlane[3] = VGLPlane[2] + i;
65     pos = 0;
66     planepos = 0;
67     last = 8 - start_offset;
68     while (pos < width) {
69       word = 0;
70       while (pos < last && pos < width)
71         word = (word<<1) | color2bit[line[pos++]&0x0f];
72       VGLPlane[0][planepos] = word;
73       VGLPlane[1][planepos] = word>>8;
74       VGLPlane[2][planepos] = word>>16;
75       VGLPlane[3][planepos] = word>>24;
76       planepos++;
77       last += 8;
78     }
79     planepos--;
80     if (end_offset) {
81       word <<= (8 - end_offset);
82       VGLPlane[0][planepos] = word;
83       VGLPlane[1][planepos] = word>>8;
84       VGLPlane[2][planepos] = word>>16;
85       VGLPlane[3][planepos] = word>>24;
86     }
87     if (start_offset || end_offset)
88       width+=8;
89     width /= 8;
90     outb(0x3ce, 0x01); outb(0x3cf, 0x00);               /* set/reset enable */
91     outb(0x3ce, 0x08); outb(0x3cf, 0xff);               /* bit mask */
92     for (i=0; i<4; i++) {
93       outb(0x3c4, 0x02);
94       outb(0x3c5, 0x01<<i);
95       outb(0x3ce, 0x04);
96       outb(0x3cf, i);
97       pos = VGLAdpInfo.va_line_width*y + x/8;
98       if (dst->Type == VIDBUF4) {
99         if (end_offset)
100           VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset];
101         if (start_offset)
102           VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset];
103         bcopy(&VGLPlane[i][0], dst->Bitmap + pos, width);
104       } else {  /* VIDBUF4S */
105         if (end_offset) {
106           offset = VGLSetSegment(pos + planepos);
107           VGLPlane[i][planepos] |= dst->Bitmap[offset] & mask[end_offset];
108         }
109         offset = VGLSetSegment(pos);
110         if (start_offset)
111           VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset];
112         for (last = width; ; ) { 
113           len = min(VGLAdpInfo.va_window_size - offset, last);
114           bcopy(&VGLPlane[i][width - last], dst->Bitmap + offset, len);
115           pos += len;
116           last -= len;
117           if (last <= 0)
118             break;
119           offset = VGLSetSegment(pos);
120         }
121       }
122     }
123     break;
124   case VIDBUF8X:
125     address = dst->Bitmap + VGLAdpInfo.va_line_width * y + x/4;
126     for (i=0; i<4; i++) {
127       outb(0x3c4, 0x02);
128       outb(0x3c5, 0x01 << ((x + i)%4));
129       for (planepos=0, pos=i; pos<width; planepos++, pos+=4)
130         address[planepos] = line[pos];
131       if ((x + i)%4 == 3)
132         ++address;
133     }
134     break;
135   case VIDBUF8S:
136     pos = dst->VXsize * y + x;
137     while (width > 0) {
138       offset = VGLSetSegment(pos);
139       i = min(VGLAdpInfo.va_window_size - offset, width);
140       bcopy(line, dst->Bitmap + offset, i);
141       line += i;
142       pos += i;
143       width -= i;
144     }
145     break;
146   case VIDBUF16S:
147   case VIDBUF24S:
148   case VIDBUF32S:
149     width = width * dst->PixelBytes;
150     pos = (dst->VXsize * y + x) * dst->PixelBytes;
151     while (width > 0) {
152       offset = VGLSetSegment(pos);
153       i = min(VGLAdpInfo.va_window_size - offset, width);
154       bcopy(line, dst->Bitmap + offset, i);
155       line += i;
156       pos += i;
157       width -= i;
158     }
159     break;
160   case VIDBUF8:
161   case MEMBUF:
162     address = dst->Bitmap + dst->VXsize * y + x;
163     bcopy(line, address, width);
164     break;
165   case VIDBUF16:
166   case VIDBUF24:
167   case VIDBUF32:
168     address = dst->Bitmap + (dst->VXsize * y + x) * dst->PixelBytes;
169     bcopy(line, address, width * dst->PixelBytes);
170     break;
171   default:
172   }
173 }
174
175 static void
176 ReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line)
177 {
178   int i, bit, pos, count, planepos, start_offset, end_offset, offset;
179   int width2, len;
180   byte *address;
181   byte *VGLPlane[4];
182
183   switch (src->Type) {
184   case VIDBUF4S:
185     start_offset = (x & 0x07);
186     end_offset = (x + width) & 0x07;
187     count = (width + start_offset) / 8;
188     if (end_offset)
189       count++;
190     VGLPlane[0] = VGLBuf;
191     VGLPlane[1] = VGLPlane[0] + count;
192     VGLPlane[2] = VGLPlane[1] + count;
193     VGLPlane[3] = VGLPlane[2] + count;
194     for (i=0; i<4; i++) {
195       outb(0x3ce, 0x04);
196       outb(0x3cf, i);
197       pos = VGLAdpInfo.va_line_width*y + x/8;
198       for (width2 = count; width2 > 0; ) {
199         offset = VGLSetSegment(pos);
200         len = min(VGLAdpInfo.va_window_size - offset, width2);
201         bcopy(src->Bitmap + offset, &VGLPlane[i][count - width2], len);
202         pos += len;
203         width2 -= len;
204       }
205     }
206     goto read_planar;
207   case VIDBUF4:
208     address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/8;
209     start_offset = (x & 0x07);
210     end_offset = (x + width) & 0x07;
211     count = (width + start_offset) / 8;
212     if (end_offset)
213       count++;
214     VGLPlane[0] = VGLBuf;
215     VGLPlane[1] = VGLPlane[0] + count;
216     VGLPlane[2] = VGLPlane[1] + count;
217     VGLPlane[3] = VGLPlane[2] + count;
218     for (i=0; i<4; i++) {
219       outb(0x3ce, 0x04);
220       outb(0x3cf, i);
221       bcopy(address, &VGLPlane[i][0], count);
222     }
223 read_planar:
224     pos = 0;
225     planepos = 0;
226     bit = 7 - start_offset;
227     while (pos < width) {
228       for (; bit >= 0 && pos < width; bit--, pos++) {
229         line[pos] = (VGLPlane[0][planepos] & (1<<bit) ? 1 : 0) |
230                     ((VGLPlane[1][planepos] & (1<<bit) ? 1 : 0) << 1) |
231                     ((VGLPlane[2][planepos] & (1<<bit) ? 1 : 0) << 2) |
232                     ((VGLPlane[3][planepos] & (1<<bit) ? 1 : 0) << 3);
233       }
234       planepos++;
235       bit = 7;
236     }
237     break;
238   case VIDBUF8X:
239     address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/4;
240     for (i=0; i<4; i++) {
241       outb(0x3ce, 0x04);
242       outb(0x3cf, (x + i)%4);
243       for (planepos=0, pos=i; pos<width; planepos++, pos+=4)
244         line[pos] = address[planepos];
245       if ((x + i)%4 == 3)
246         ++address;
247     }
248     break;
249   case VIDBUF8S:
250     pos = src->VXsize * y + x;
251     while (width > 0) {
252       offset = VGLSetSegment(pos);
253       i = min(VGLAdpInfo.va_window_size - offset, width);
254       bcopy(src->Bitmap + offset, line, i);
255       line += i;
256       pos += i;
257       width -= i;
258     }
259     break;
260   case VIDBUF16S:
261   case VIDBUF24S:
262   case VIDBUF32S:
263     width = width * src->PixelBytes;
264     pos = (src->VXsize * y + x) * src->PixelBytes;
265     while (width > 0) {
266       offset = VGLSetSegment(pos);
267       i = min(VGLAdpInfo.va_window_size - offset, width);
268       bcopy(src->Bitmap + offset, line, i);
269       line += i;
270       pos += i;
271       width -= i;
272     }
273     break;
274   case VIDBUF8:
275   case MEMBUF:
276     address = src->Bitmap + src->VXsize * y + x;
277     bcopy(address, line, width);
278     break;
279   case VIDBUF16:
280   case VIDBUF24:
281   case VIDBUF32:
282     address = src->Bitmap + (src->VXsize * y + x) * src->PixelBytes;
283     bcopy(address, line, width * src->PixelBytes);
284     break;
285   default:
286   }
287 }
288
289 int
290 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
291               VGLBitmap *dst, int dstx, int dsty, int width, int hight)
292 {
293   int srcline, dstline;
294
295   if (srcx>src->VXsize || srcy>src->VYsize
296         || dstx>dst->VXsize || dsty>dst->VYsize)
297     return -1;  
298   if (srcx < 0) {
299     width=width+srcx; dstx-=srcx; srcx=0;    
300   }
301   if (srcy < 0) {
302     hight=hight+srcy; dsty-=srcy; srcy=0; 
303   }
304   if (dstx < 0) {    
305     width=width+dstx; srcx-=dstx; dstx=0;
306   }
307   if (dsty < 0) {
308     hight=hight+dsty; srcy-=dsty; dsty=0;
309   }
310   if (srcx+width > src->VXsize)
311      width=src->VXsize-srcx;
312   if (srcy+hight > src->VYsize)
313      hight=src->VYsize-srcy;
314   if (dstx+width > dst->VXsize)
315      width=dst->VXsize-dstx;
316   if (dsty+hight > dst->VYsize)
317      hight=dst->VYsize-dsty;
318   if (width < 0 || hight < 0)
319      return -1;
320   if (src->Type == MEMBUF) {
321     for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
322       WriteVerticalLine(dst, dstx, dstline, width, 
323         (src->Bitmap+(srcline*src->VXsize)+srcx));
324     }
325   }
326   else if (dst->Type == MEMBUF) {
327     for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
328       ReadVerticalLine(src, srcx, srcline, width,
329          (dst->Bitmap+(dstline*dst->VXsize)+dstx));
330     }
331   }
332   else {
333     byte buffer[2048];  /* XXX */
334     byte *p;
335
336     if (width > sizeof(buffer)) {
337       p = malloc(width);
338       if (p == NULL)
339         return 1;
340     } else {
341       p = buffer;
342     }
343     for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) {
344       ReadVerticalLine(src, srcx, srcline, width, p);
345       WriteVerticalLine(dst, dstx, dstline, width, p);
346     }
347     if (width > sizeof(buffer))
348       free(p);
349   }
350   return 0;
351 }
352
353 int
354 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy,
355               VGLBitmap *dst, int dstx, int dsty, int width, int hight)
356 {
357   int error;
358
359   VGLMouseFreeze(dstx, dsty, width, hight, 0);
360   error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight);
361   VGLMouseUnFreeze();
362   return error;
363 }
364
365 VGLBitmap
366 *VGLBitmapCreate(int type, int xsize, int ysize, byte *bits)
367 {
368   VGLBitmap *object;
369
370   if (type != MEMBUF)
371     return NULL;
372   if (xsize < 0 || ysize < 0)
373     return NULL;
374   object = (VGLBitmap *)malloc(sizeof(*object));
375   if (object == NULL)
376     return NULL;
377   object->Type = type;
378   object->Xsize = xsize;
379   object->Ysize = ysize;
380   object->VXsize = xsize;
381   object->VYsize = ysize;
382   object->Xorigin = 0;
383   object->Yorigin = 0;
384   object->Bitmap = bits;
385   return object;
386 }
387
388 void
389 VGLBitmapDestroy(VGLBitmap *object)
390 {
391   if (object->Bitmap)
392     free(object->Bitmap);
393   free(object);
394 }
395
396 int
397 VGLBitmapAllocateBits(VGLBitmap *object)
398 {
399   object->Bitmap = (byte *)malloc(object->VXsize*object->VYsize);
400   if (object->Bitmap == NULL)
401     return -1;
402   return 0;
403 }