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/cdefs.h> 32 #include <sys/types.h> 33 #include <signal.h> 34 #include <sys/fbio.h> 35 #include "vgl.h" 36 37 #define min(x, y) (((x) < (y)) ? (x) : (y)) 38 39 static byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; 40 static int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101, 41 0x00010000, 0x00010001, 0x00010100, 0x00010101, 42 0x01000000, 0x01000001, 0x01000100, 0x01000101, 43 0x01010000, 0x01010001, 0x01010100, 0x01010101}; 44 45 static void 46 WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) 47 { 48 int bwidth, i, pos, last, planepos, start_offset, end_offset, offset; 49 int len; 50 unsigned int word = 0; 51 byte *address; 52 byte *VGLPlane[4]; 53 54 switch (dst->Type) { 55 case VIDBUF4: 56 case VIDBUF4S: 57 start_offset = (x & 0x07); 58 end_offset = (x + width) & 0x07; 59 bwidth = (width + start_offset) / 8; 60 if (end_offset) 61 bwidth++; 62 VGLPlane[0] = VGLBuf; 63 VGLPlane[1] = VGLPlane[0] + bwidth; 64 VGLPlane[2] = VGLPlane[1] + bwidth; 65 VGLPlane[3] = VGLPlane[2] + bwidth; 66 pos = 0; 67 planepos = 0; 68 last = 8 - start_offset; 69 while (pos < width) { 70 word = 0; 71 while (pos < last && pos < width) 72 word = (word<<1) | color2bit[line[pos++]&0x0f]; 73 VGLPlane[0][planepos] = word; 74 VGLPlane[1][planepos] = word>>8; 75 VGLPlane[2][planepos] = word>>16; 76 VGLPlane[3][planepos] = word>>24; 77 planepos++; 78 last += 8; 79 } 80 planepos--; 81 if (end_offset) { 82 word <<= (8 - end_offset); 83 VGLPlane[0][planepos] = word; 84 VGLPlane[1][planepos] = word>>8; 85 VGLPlane[2][planepos] = word>>16; 86 VGLPlane[3][planepos] = word>>24; 87 } 88 outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 89 outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 90 for (i=0; i<4; i++) { 91 outb(0x3c4, 0x02); 92 outb(0x3c5, 0x01<<i); 93 outb(0x3ce, 0x04); 94 outb(0x3cf, i); 95 pos = VGLAdpInfo.va_line_width*y + x/8; 96 if (dst->Type == VIDBUF4) { 97 if (end_offset) 98 VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset]; 99 if (start_offset) 100 VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset]; 101 bcopy(&VGLPlane[i][0], dst->Bitmap + pos, bwidth); 102 } else { /* VIDBUF4S */ 103 if (end_offset) { 104 offset = VGLSetSegment(pos + planepos); 105 VGLPlane[i][planepos] |= dst->Bitmap[offset] & mask[end_offset]; 106 } 107 offset = VGLSetSegment(pos); 108 if (start_offset) 109 VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset]; 110 for (last = bwidth; ; ) { 111 len = min(VGLAdpInfo.va_window_size - offset, last); 112 bcopy(&VGLPlane[i][bwidth - last], dst->Bitmap + offset, len); 113 pos += len; 114 last -= len; 115 if (last <= 0) 116 break; 117 offset = VGLSetSegment(pos); 118 } 119 } 120 } 121 break; 122 case VIDBUF8X: 123 address = dst->Bitmap + VGLAdpInfo.va_line_width * y + x/4; 124 for (i=0; i<4; i++) { 125 outb(0x3c4, 0x02); 126 outb(0x3c5, 0x01 << ((x + i)%4)); 127 for (planepos=0, pos=i; pos<width; planepos++, pos+=4) 128 address[planepos] = line[pos]; 129 if ((x + i)%4 == 3) 130 ++address; 131 } 132 break; 133 case VIDBUF8S: 134 case VIDBUF16S: 135 case VIDBUF24S: 136 case VIDBUF32S: 137 width = width * dst->PixelBytes; 138 pos = (dst->VXsize * y + x) * dst->PixelBytes; 139 while (width > 0) { 140 offset = VGLSetSegment(pos); 141 i = min(VGLAdpInfo.va_window_size - offset, width); 142 bcopy(line, dst->Bitmap + offset, i); 143 line += i; 144 pos += i; 145 width -= i; 146 } 147 break; 148 case MEMBUF: 149 case VIDBUF8: 150 case VIDBUF16: 151 case VIDBUF24: 152 case VIDBUF32: 153 address = dst->Bitmap + (dst->VXsize * y + x) * dst->PixelBytes; 154 bcopy(line, address, width * dst->PixelBytes); 155 break; 156 default: 157 ; 158 } 159 } 160 161 int 162 __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 163 VGLBitmap *dst, int dstx, int dsty, int width, int hight) 164 { 165 byte *buffer, *p; 166 int mousemerge, srcline, dstline, yend, yextra, ystep; 167 168 mousemerge = 0; 169 if (hight < 0) { 170 hight = -hight; 171 mousemerge = (dst == VGLDisplay && 172 VGLMouseOverlap(dstx, dsty, width, hight)); 173 if (mousemerge) 174 buffer = alloca(width*src->PixelBytes); 175 } 176 if (srcx>src->VXsize || srcy>src->VYsize 177 || dstx>dst->VXsize || dsty>dst->VYsize) 178 return -1; 179 if (srcx < 0) { 180 width=width+srcx; dstx-=srcx; srcx=0; 181 } 182 if (srcy < 0) { 183 hight=hight+srcy; dsty-=srcy; srcy=0; 184 } 185 if (dstx < 0) { 186 width=width+dstx; srcx-=dstx; dstx=0; 187 } 188 if (dsty < 0) { 189 hight=hight+dsty; srcy-=dsty; dsty=0; 190 } 191 if (srcx+width > src->VXsize) 192 width=src->VXsize-srcx; 193 if (srcy+hight > src->VYsize) 194 hight=src->VYsize-srcy; 195 if (dstx+width > dst->VXsize) 196 width=dst->VXsize-dstx; 197 if (dsty+hight > dst->VYsize) 198 hight=dst->VYsize-dsty; 199 if (width < 0 || hight < 0) 200 return -1; 201 yend = srcy + hight; 202 yextra = 0; 203 ystep = 1; 204 if (src->Bitmap == dst->Bitmap && srcy < dsty) { 205 yend = srcy - 1; 206 yextra = hight - 1; 207 ystep = -1; 208 } 209 for (srcline = srcy + yextra, dstline = dsty + yextra; srcline != yend; 210 srcline += ystep, dstline += ystep) { 211 p = src->Bitmap+(srcline*src->VXsize+srcx)*dst->PixelBytes; 212 if (mousemerge && VGLMouseOverlap(dstx, dstline, width, 1)) { 213 bcopy(p, buffer, width*src->PixelBytes); 214 p = buffer; 215 VGLMouseMerge(dstx, dstline, width, p); 216 } 217 WriteVerticalLine(dst, dstx, dstline, width, p); 218 } 219 return 0; 220 } 221 222 int 223 VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 224 VGLBitmap *dst, int dstx, int dsty, int width, int hight) 225 { 226 int error; 227 228 if (hight < 0) 229 return -1; 230 if (src == VGLDisplay) 231 src = &VGLVDisplay; 232 if (src->Type != MEMBUF) 233 return -1; /* invalid */ 234 if (dst == VGLDisplay) { 235 VGLMouseFreeze(); 236 __VGLBitmapCopy(src, srcx, srcy, &VGLVDisplay, dstx, dsty, width, hight); 237 error = __VGLBitmapCopy(src, srcx, srcy, &VGLVDisplay, dstx, dsty, 238 width, hight); 239 if (error != 0) 240 return error; 241 src = &VGLVDisplay; 242 srcx = dstx; 243 srcy = dsty; 244 } else if (dst->Type != MEMBUF) 245 return -1; /* invalid */ 246 error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, -hight); 247 if (dst == VGLDisplay) 248 VGLMouseUnFreeze(); 249 return error; 250 } 251 252 VGLBitmap 253 *VGLBitmapCreate(int type, int xsize, int ysize, byte *bits) 254 { 255 VGLBitmap *object; 256 257 if (type != MEMBUF) 258 return NULL; 259 if (xsize < 0 || ysize < 0) 260 return NULL; 261 object = (VGLBitmap *)malloc(sizeof(*object)); 262 if (object == NULL) 263 return NULL; 264 object->Type = type; 265 object->Xsize = xsize; 266 object->Ysize = ysize; 267 object->VXsize = xsize; 268 object->VYsize = ysize; 269 object->Xorigin = 0; 270 object->Yorigin = 0; 271 object->Bitmap = bits; 272 object->PixelBytes = VGLDisplay->PixelBytes; 273 return object; 274 } 275 276 void 277 VGLBitmapDestroy(VGLBitmap *object) 278 { 279 if (object->Bitmap) 280 free(object->Bitmap); 281 free(object); 282 } 283 284 int 285 VGLBitmapAllocateBits(VGLBitmap *object) 286 { 287 object->Bitmap = malloc(object->VXsize*object->VYsize*object->PixelBytes); 288 if (object->Bitmap == NULL) 289 return -1; 290 return 0; 291 } 292 293 void 294 VGLBitmapCvt(VGLBitmap *src, VGLBitmap *dst) 295 { 296 u_long color; 297 int dstpos, i, pb, size, srcpb, srcpos; 298 299 size = src->VXsize * src->VYsize; 300 srcpb = src->PixelBytes; 301 if (srcpb <= 0) 302 srcpb = 1; 303 pb = dst->PixelBytes; 304 if (pb == srcpb) { 305 bcopy(src->Bitmap, dst->Bitmap, size * pb); 306 return; 307 } 308 if (srcpb != 1) 309 return; /* not supported */ 310 for (srcpos = dstpos = 0; srcpos < size; srcpos++) { 311 color = VGLrgb332ToNative(src->Bitmap[srcpos]); 312 for (i = 0; i < pb; i++, color >>= 8) 313 dst->Bitmap[dstpos++] = color; 314 } 315 } 316