1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1991-1997 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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 bwidth, 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 bwidth = (width + start_offset) / 8; 59 if (end_offset) 60 bwidth++; 61 VGLPlane[0] = VGLBuf; 62 VGLPlane[1] = VGLPlane[0] + bwidth; 63 VGLPlane[2] = VGLPlane[1] + bwidth; 64 VGLPlane[3] = VGLPlane[2] + bwidth; 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 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 88 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 89 for (i=0; i<4; i++) { 90 outb(0x3c4, 0x02); 91 outb(0x3c5, 0x01<<i); 92 outb(0x3ce, 0x04); 93 outb(0x3cf, i); 94 pos = VGLAdpInfo.va_line_width*y + x/8; 95 if (dst->Type == VIDBUF4) { 96 if (end_offset) 97 VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset]; 98 if (start_offset) 99 VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset]; 100 bcopy(&VGLPlane[i][0], dst->Bitmap + pos, bwidth); 101 } else { /* VIDBUF4S */ 102 if (end_offset) { 103 offset = VGLSetSegment(pos + planepos); 104 VGLPlane[i][planepos] |= dst->Bitmap[offset] & mask[end_offset]; 105 } 106 offset = VGLSetSegment(pos); 107 if (start_offset) 108 VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset]; 109 for (last = bwidth; ; ) { 110 len = min(VGLAdpInfo.va_window_size - offset, last); 111 bcopy(&VGLPlane[i][bwidth - last], dst->Bitmap + offset, len); 112 pos += len; 113 last -= len; 114 if (last <= 0) 115 break; 116 offset = VGLSetSegment(pos); 117 } 118 } 119 } 120 break; 121 case VIDBUF8X: 122 address = dst->Bitmap + VGLAdpInfo.va_line_width * y + x/4; 123 for (i=0; i<4; i++) { 124 outb(0x3c4, 0x02); 125 outb(0x3c5, 0x01 << ((x + i)%4)); 126 for (planepos=0, pos=i; pos<width; planepos++, pos+=4) 127 address[planepos] = line[pos]; 128 if ((x + i)%4 == 3) 129 ++address; 130 } 131 break; 132 case VIDBUF8S: 133 case VIDBUF16S: 134 case VIDBUF24S: 135 case VIDBUF32S: 136 width = width * dst->PixelBytes; 137 pos = (dst->VXsize * y + x) * dst->PixelBytes; 138 while (width > 0) { 139 offset = VGLSetSegment(pos); 140 i = min(VGLAdpInfo.va_window_size - offset, width); 141 bcopy(line, dst->Bitmap + offset, i); 142 line += i; 143 pos += i; 144 width -= i; 145 } 146 break; 147 case MEMBUF: 148 case VIDBUF8: 149 case VIDBUF16: 150 case VIDBUF24: 151 case VIDBUF32: 152 address = dst->Bitmap + (dst->VXsize * y + x) * dst->PixelBytes; 153 bcopy(line, address, width * dst->PixelBytes); 154 break; 155 default: 156 ; 157 } 158 } 159 160 int 161 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 162 VGLBitmap *dst, int dstx, int dsty, int width, int hight) 163 { 164 byte *buffer, *p; 165 int mousemerge, srcline, dstline, yend, yextra, ystep; 166 167 mousemerge = 0; 168 if (hight < 0) { 169 hight = -hight; 170 mousemerge = (dst == VGLDisplay && 171 VGLMouseOverlap(dstx, dsty, width, hight)); 172 if (mousemerge) 173 buffer = alloca(width*src->PixelBytes); 174 } 175 if (srcx>src->VXsize || srcy>src->VYsize 176 || dstx>dst->VXsize || dsty>dst->VYsize) 177 return -1; 178 if (srcx < 0) { 179 width=width+srcx; dstx-=srcx; srcx=0; 180 } 181 if (srcy < 0) { 182 hight=hight+srcy; dsty-=srcy; srcy=0; 183 } 184 if (dstx < 0) { 185 width=width+dstx; srcx-=dstx; dstx=0; 186 } 187 if (dsty < 0) { 188 hight=hight+dsty; srcy-=dsty; dsty=0; 189 } 190 if (srcx+width > src->VXsize) 191 width=src->VXsize-srcx; 192 if (srcy+hight > src->VYsize) 193 hight=src->VYsize-srcy; 194 if (dstx+width > dst->VXsize) 195 width=dst->VXsize-dstx; 196 if (dsty+hight > dst->VYsize) 197 hight=dst->VYsize-dsty; 198 if (width < 0 || hight < 0) 199 return -1; 200 yend = srcy + hight; 201 yextra = 0; 202 ystep = 1; 203 if (src->Bitmap == dst->Bitmap && srcy < dsty) { 204 yend = srcy - 1; 205 yextra = hight - 1; 206 ystep = -1; 207 } 208 for (srcline = srcy + yextra, dstline = dsty + yextra; srcline != yend; 209 srcline += ystep, dstline += ystep) { 210 p = src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes; 211 if (mousemerge && VGLMouseOverlap(dstx, dstline, width, 1)) { 212 bcopy(p, buffer, width*src->PixelBytes); 213 p = buffer; 214 VGLMouseMerge(dstx, dstline, width, p); 215 } 216 WriteVerticalLine(dst, dstx, dstline, width, p); 217 } 218 return 0; 219 } 220 221 int 222 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 223 VGLBitmap *dst, int dstx, int dsty, int width, int hight) 224 { 225 int error; 226 227 if (hight < 0) 228 return -1; 229 if (src == VGLDisplay) 230 src = &VGLVDisplay; 231 if (src->Type != MEMBUF) 232 return -1; /* invalid */ 233 if (dst == VGLDisplay) { 234 VGLMouseFreeze(); 235 __VGLBitmapCopy(src, srcx, srcy, &VGLVDisplay, dstx, dsty, width, hight); 236 error = __VGLBitmapCopy(src, srcx, srcy, &VGLVDisplay, dstx, dsty, 237 width, hight); 238 if (error != 0) 239 return error; 240 src = &VGLVDisplay; 241 srcx = dstx; 242 srcy = dsty; 243 } else if (dst->Type != MEMBUF) 244 return -1; /* invalid */ 245 error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, -hight); 246 if (dst == VGLDisplay) 247 VGLMouseUnFreeze(); 248 return error; 249 } 250 251 VGLBitmap 252 *VGLBitmapCreate(int type, int xsize, int ysize, byte *bits) 253 { 254 VGLBitmap *object; 255 256 if (type != MEMBUF) 257 return NULL; 258 if (xsize < 0 || ysize < 0) 259 return NULL; 260 object = (VGLBitmap *)malloc(sizeof(*object)); 261 if (object == NULL) 262 return NULL; 263 object->Type = type; 264 object->Xsize = xsize; 265 object->Ysize = ysize; 266 object->VXsize = xsize; 267 object->VYsize = ysize; 268 object->Xorigin = 0; 269 object->Yorigin = 0; 270 object->Bitmap = bits; 271 object->PixelBytes = VGLDisplay->PixelBytes; 272 return object; 273 } 274 275 void 276 VGLBitmapDestroy(VGLBitmap *object) 277 { 278 if (object->Bitmap) 279 free(object->Bitmap); 280 free(object); 281 } 282 283 int 284 VGLBitmapAllocateBits(VGLBitmap *object) 285 { 286 object->Bitmap = malloc(object->VXsize*object->VYsize*object->PixelBytes); 287 if (object->Bitmap == NULL) 288 return -1; 289 return 0; 290 } 291 292 void 293 VGLBitmapCvt(VGLBitmap *src, VGLBitmap *dst) 294 { 295 u_long color; 296 int dstpos, i, pb, size, srcpb, srcpos; 297 298 size = src->VXsize * src->VYsize; 299 srcpb = src->PixelBytes; 300 if (srcpb <= 0) 301 srcpb = 1; 302 pb = dst->PixelBytes; 303 if (pb == srcpb) { 304 bcopy(src->Bitmap, dst->Bitmap, size * pb); 305 return; 306 } 307 if (srcpb != 1) 308 return; /* not supported */ 309 for (srcpos = dstpos = 0; srcpos < size; srcpos++) { 310 color = VGLrgb332ToNative(src->Bitmap[srcpos]); 311 for (i = 0; i < pb; i++, color >>= 8) 312 dst->Bitmap[dstpos++] = color; 313 } 314 } 315