14Srgrimes/*- 2122296Speter * Copyright (c) 1991-1997 S��ren Schmidt 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * Redistribution and use in source and binary forms, with or without 64Srgrimes * modification, are permitted provided that the following conditions 74Srgrimes * are met: 84Srgrimes * 1. Redistributions of source code must retain the above copyright 94Srgrimes * notice, this list of conditions and the following disclaimer, 104Srgrimes * in this position and unchanged. 114Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer in the 134Srgrimes * documentation and/or other materials provided with the distribution. 144Srgrimes * 3. The name of the author may not be used to endorse or promote products 154Srgrimes * derived from this software without specific prior written permission. 164Srgrimes * 174Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 184Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 194Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 204Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 214Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 224Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 264Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274Srgrimes */ 284Srgrimes 294Srgrimes#include <sys/cdefs.h> 30122940Speter__FBSDID("$FreeBSD: releng/10.3/lib/libvgl/bitmap.c 229784 2012-01-07 16:13:56Z uqs $"); 314Srgrimes 324Srgrimes#include <sys/types.h> 33118031Sobrien#include <signal.h> 34118031Sobrien#include <sys/fbio.h> 35118031Sobrien#include "vgl.h" 36223668Sjonathan 37219134Srwatson#define min(x, y) (((x) < (y)) ? (x) : (y)) 382056Swollman 392056Swollmanstatic byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; 40219134Srwatsonstatic int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101, 41217564Skib 0x00010000, 0x00010001, 0x00010100, 0x00010101, 4276166Smarkm 0x01000000, 0x01000001, 0x01000100, 0x01000101, 43190620Skib 0x01010000, 0x01010001, 0x01010100, 0x01010101}; 44190620Skib 45190620Skibstatic void 462056SwollmanWriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) 4776166Smarkm{ 48190620Skib int i, pos, last, planepos, start_offset, end_offset, offset; 4912662Sdg int len; 50147889Sdavidxu unsigned int word = 0; 51147889Sdavidxu byte *address; 52190620Skib byte *VGLPlane[4]; 53190620Skib 54190620Skib switch (dst->Type) { 55190620Skib case VIDBUF4: 56190620Skib case VIDBUF4S: 57190620Skib start_offset = (x & 0x07); 58190620Skib end_offset = (x + width) & 0x07; 59190620Skib i = (width + start_offset) / 8; 60190620Skib if (end_offset) 61147889Sdavidxu i++; 62147889Sdavidxu VGLPlane[0] = VGLBuf; 63190620Skib VGLPlane[1] = VGLPlane[0] + i; 64190620Skib VGLPlane[2] = VGLPlane[1] + i; 65217564Skib VGLPlane[3] = VGLPlane[2] + i; 66217564Skib pos = 0; 67190620Skib planepos = 0; 68217604Skib last = 8 - start_offset; 69217604Skib while (pos < width) { 70217564Skib word = 0; 71190620Skib while (pos < last && pos < width) 72217564Skib word = (word<<1) | color2bit[line[pos++]&0x0f]; 73217564Skib VGLPlane[0][planepos] = word; 74217564Skib VGLPlane[1][planepos] = word>>8; 75217564Skib VGLPlane[2][planepos] = word>>16; 76217564Skib VGLPlane[3][planepos] = word>>24; 77217564Skib planepos++; 78217564Skib last += 8; 79217564Skib } 80217564Skib planepos--; 81217564Skib if (end_offset) { 82217564Skib word <<= (8 - end_offset); 83217564Skib VGLPlane[0][planepos] = word; 84190620Skib VGLPlane[1][planepos] = word>>8; 85190620Skib VGLPlane[2][planepos] = word>>16; 86190620Skib VGLPlane[3][planepos] = word>>24; 87190620Skib } 88190620Skib if (start_offset || end_offset) 89190620Skib width+=8; 90190620Skib width /= 8; 9112220Sbde outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ 926874Sdg outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ 936874Sdg for (i=0; i<4; i++) { 946874Sdg outb(0x3c4, 0x02); 95132Sdg outb(0x3c5, 0x01<<i); 9612220Sbde outb(0x3ce, 0x04); 97132Sdg outb(0x3cf, i); 986874Sdg pos = VGLAdpInfo.va_line_width*y + x/8; 99190620Skib if (dst->Type == VIDBUF4) { 100190620Skib if (end_offset) 101190620Skib VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset]; 102190620Skib if (start_offset) 103190620Skib VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset]; 104190620Skib bcopy(&VGLPlane[i][0], dst->Bitmap + pos, width); 105190620Skib } else { /* VIDBUF4S */ 106190620Skib if (end_offset) { 107190620Skib offset = VGLSetSegment(pos + planepos); 108190620Skib VGLPlane[i][planepos] |= dst->Bitmap[offset] & mask[end_offset]; 109195104Srwatson } 110190620Skib offset = VGLSetSegment(pos); 111190620Skib if (start_offset) 112190620Skib VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset]; 113190620Skib for (last = width; ; ) { 114190620Skib len = min(VGLAdpInfo.va_window_size - offset, last); 115190620Skib bcopy(&VGLPlane[i][width - last], dst->Bitmap + offset, len); 116190620Skib pos += len; 117190620Skib last -= len; 118190620Skib if (last <= 0) 119190620Skib break; 120190620Skib offset = VGLSetSegment(pos); 121190620Skib } 122190620Skib } 123217543Sjhb } 124217543Sjhb break; 125216634Sjkim case VIDBUF8X: 126190620Skib address = dst->Bitmap + VGLAdpInfo.va_line_width * y + x/4; 127217563Skib for (i=0; i<4; i++) { 128217563Skib outb(0x3c4, 0x02); 129190620Skib outb(0x3c5, 0x01 << ((x + i)%4)); 130190620Skib for (planepos=0, pos=i; pos<width; planepos++, pos+=4) 131190620Skib address[planepos] = line[pos]; 132190620Skib if ((x + i)%4 == 3) 133217563Skib ++address; 134190620Skib } 135190620Skib break; 136190620Skib case VIDBUF8S: 137190620Skib pos = dst->VXsize * y + x; 138190620Skib while (width > 0) { 139190620Skib offset = VGLSetSegment(pos); 140190620Skib i = min(VGLAdpInfo.va_window_size - offset, width); 141190620Skib bcopy(line, dst->Bitmap + offset, i); 142190620Skib line += i; 143190620Skib pos += i; 144190620Skib width -= i; 145190620Skib } 146190620Skib break; 147190620Skib case VIDBUF16S: 148190620Skib case VIDBUF24S: 149216634Sjkim case VIDBUF32S: 150190620Skib width = width * dst->PixelBytes; 151190620Skib pos = (dst->VXsize * y + x) * dst->PixelBytes; 152190620Skib while (width > 0) { 153190620Skib offset = VGLSetSegment(pos); 154190620Skib i = min(VGLAdpInfo.va_window_size - offset, width); 155190620Skib bcopy(line, dst->Bitmap + offset, i); 156190620Skib line += i; 157190620Skib pos += i; 158190620Skib width -= i; 159190620Skib } 160190620Skib break; 161190620Skib case VIDBUF8: 162190620Skib case MEMBUF: 163190620Skib address = dst->Bitmap + dst->VXsize * y + x; 164216634Sjkim bcopy(line, address, width); 165190620Skib break; 166190620Skib case VIDBUF16: 167190620Skib case VIDBUF24: 168190620Skib case VIDBUF32: 169190620Skib address = dst->Bitmap + (dst->VXsize * y + x) * dst->PixelBytes; 170190620Skib bcopy(line, address, width * dst->PixelBytes); 171190620Skib break; 172190620Skib default: 17383366Sjulian ; 17483366Sjulian } 1756874Sdg} 1764Srgrimes 177114928Speterstatic void 178114928SpeterReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line) 179145077Speter{ 180147889Sdavidxu int i, bit, pos, count, planepos, start_offset, end_offset, offset; 181190620Skib int width2, len; 182230426Skib byte *address; 183230426Skib byte *VGLPlane[4]; 1844Srgrimes 185223668Sjonathan switch (src->Type) { 186219134Srwatson case VIDBUF4S: 187223692Sjonathan start_offset = (x & 0x07); 188223692Sjonathan end_offset = (x + width) & 0x07; 189223692Sjonathan count = (width + start_offset) / 8; 190219134Srwatson if (end_offset) 191219134Srwatson count++; 192219134Srwatson VGLPlane[0] = VGLBuf; 193223692Sjonathan VGLPlane[1] = VGLPlane[0] + count; 194223692Sjonathan VGLPlane[2] = VGLPlane[1] + count; 195223692Sjonathan VGLPlane[3] = VGLPlane[2] + count; 196223692Sjonathan for (i=0; i<4; i++) { 197223692Sjonathan outb(0x3ce, 0x04); 198223692Sjonathan outb(0x3cf, i); 199223692Sjonathan pos = VGLAdpInfo.va_line_width*y + x/8; 200230426Skib for (width2 = count; width2 > 0; ) { 201223692Sjonathan offset = VGLSetSegment(pos); 202223692Sjonathan len = min(VGLAdpInfo.va_window_size - offset, width2); 203223692Sjonathan bcopy(src->Bitmap + offset, &VGLPlane[i][count - width2], len); 204223692Sjonathan pos += len; 205230426Skib width2 -= len; 206223692Sjonathan } 207219134Srwatson } 208223692Sjonathan goto read_planar; 209223692Sjonathan case VIDBUF4: 210226498Sdes address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/8; 211226498Sdes start_offset = (x & 0x07); 212255677Spjd end_offset = (x + width) & 0x07; 213226498Sdes count = (width + start_offset) / 8; 214223692Sjonathan if (end_offset) 215219134Srwatson count++; 216219134Srwatson VGLPlane[0] = VGLBuf; 217219134Srwatson VGLPlane[1] = VGLPlane[0] + count; 218219134Srwatson VGLPlane[2] = VGLPlane[1] + count; 219190620Skib VGLPlane[3] = VGLPlane[2] + count; 220190620Skib for (i=0; i<4; i++) { 221190620Skib outb(0x3ce, 0x04); 222190620Skib outb(0x3cf, i); 223190620Skib bcopy(address, &VGLPlane[i][0], count); 224190620Skib } 225195105Srwatsonread_planar: 226190620Skib pos = 0; 227190620Skib planepos = 0; 228190620Skib bit = 7 - start_offset; 229190620Skib while (pos < width) { 230190620Skib for (; bit >= 0 && pos < width; bit--, pos++) { 231190620Skib line[pos] = (VGLPlane[0][planepos] & (1<<bit) ? 1 : 0) | 232190620Skib ((VGLPlane[1][planepos] & (1<<bit) ? 1 : 0) << 1) | 233230426Skib ((VGLPlane[2][planepos] & (1<<bit) ? 1 : 0) << 2) | 234230426Skib ((VGLPlane[3][planepos] & (1<<bit) ? 1 : 0) << 3); 235230426Skib } 236230426Skib planepos++; 237230426Skib bit = 7; 238230426Skib } 239230426Skib break; 240230426Skib case VIDBUF8X: 241230426Skib address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/4; 242230426Skib for (i=0; i<4; i++) { 243230426Skib outb(0x3ce, 0x04); 244230426Skib outb(0x3cf, (x + i)%4); 245190620Skib for (planepos=0, pos=i; pos<width; planepos++, pos+=4) 246190620Skib line[pos] = address[planepos]; 247190620Skib if ((x + i)%4 == 3) 248190620Skib ++address; 249190620Skib } 250190620Skib break; 251190620Skib case VIDBUF8S: 252190620Skib pos = src->VXsize * y + x; 253190620Skib while (width > 0) { 254190620Skib offset = VGLSetSegment(pos); 255190620Skib i = min(VGLAdpInfo.va_window_size - offset, width); 256190620Skib bcopy(src->Bitmap + offset, line, i); 257190620Skib line += i; 258190620Skib pos += i; 259145077Speter width -= i; 260145077Speter } 261145077Speter break; 262145077Speter case VIDBUF16S: 263145077Speter case VIDBUF24S: 264145077Speter case VIDBUF32S: 265147889Sdavidxu width = width * src->PixelBytes; 266147889Sdavidxu pos = (src->VXsize * y + x) * src->PixelBytes; 267190620Skib while (width > 0) { 268190620Skib offset = VGLSetSegment(pos); 269147889Sdavidxu i = min(VGLAdpInfo.va_window_size - offset, width); 270145077Speter bcopy(src->Bitmap + offset, line, i); 271145077Speter line += i; 272145077Speter pos += i; 273145077Speter width -= i; 274145077Speter } 275145077Speter break; 276145077Speter case VIDBUF8: 277147889Sdavidxu case MEMBUF: 278147889Sdavidxu address = src->Bitmap + src->VXsize * y + x; 279190620Skib bcopy(address, line, width); 280190620Skib break; 281147889Sdavidxu case VIDBUF16: 282145077Speter case VIDBUF24: 283114928Speter case VIDBUF32: 284114928Speter address = src->Bitmap + (src->VXsize * y + x) * src->PixelBytes; 285114928Speter bcopy(address, line, width * src->PixelBytes); 286114928Speter break; 287114928Speter default: 288147889Sdavidxu ; 289147889Sdavidxu } 290147889Sdavidxu} 291147889Sdavidxu 292216634Sjkimint 293190620Skib__VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 294190620Skib VGLBitmap *dst, int dstx, int dsty, int width, int hight) 295147889Sdavidxu{ 296147889Sdavidxu int srcline, dstline; 297114928Speter 298114928Speter if (srcx>src->VXsize || srcy>src->VYsize 299114928Speter || dstx>dst->VXsize || dsty>dst->VYsize) 300114928Speter return -1; 301114928Speter if (srcx < 0) { 302114928Speter width=width+srcx; dstx-=srcx; srcx=0; 303114928Speter } 304147889Sdavidxu if (srcy < 0) { 305147889Sdavidxu hight=hight+srcy; dsty-=srcy; srcy=0; 306147889Sdavidxu } 307147889Sdavidxu if (dstx < 0) { 308216634Sjkim width=width+dstx; srcx-=dstx; dstx=0; 309190620Skib } 310190620Skib if (dsty < 0) { 311147889Sdavidxu hight=hight+dsty; srcy-=dsty; dsty=0; 312147889Sdavidxu } 313114928Speter if (srcx+width > src->VXsize) 314114928Speter width=src->VXsize-srcx; 315230426Skib if (srcy+hight > src->VYsize) 316230426Skib hight=src->VYsize-srcy; 317230426Skib if (dstx+width > dst->VXsize) 318230426Skib width=dst->VXsize-dstx; 319230426Skib if (dsty+hight > dst->VYsize) 320230426Skib hight=dst->VYsize-dsty; 321230426Skib if (width < 0 || hight < 0) 322230426Skib return -1; 323230426Skib if (src->Type == MEMBUF) { 324230426Skib for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { 3256874Sdg WriteVerticalLine(dst, dstx, dstline, width, 326114029Sjhb (src->Bitmap+(srcline*src->VXsize)+srcx)); 3274Srgrimes } 3284Srgrimes } 32927993Sdyson else if (dst->Type == MEMBUF) { 3304Srgrimes for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { 331190620Skib ReadVerticalLine(src, srcx, srcline, width, 332190620Skib (dst->Bitmap+(dstline*dst->VXsize)+dstx)); 333190620Skib } 334190620Skib } 335190620Skib else { 336190620Skib byte buffer[2048]; /* XXX */ 337190620Skib byte *p; 338190620Skib 339190620Skib if (width > sizeof(buffer)) { 340190620Skib p = malloc(width); 341190620Skib if (p == NULL) 342190620Skib return 1; 343190620Skib } else { 344190620Skib p = buffer; 345190620Skib } 346190620Skib for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { 347190620Skib ReadVerticalLine(src, srcx, srcline, width, p); 348190620Skib WriteVerticalLine(dst, dstx, dstline, width, p); 349190620Skib } 350190620Skib if (width > sizeof(buffer)) 351190620Skib free(p); 352190620Skib } 353190620Skib return 0; 354190620Skib} 355190620Skib 356190620Skibint 357190620SkibVGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, 358190620Skib VGLBitmap *dst, int dstx, int dsty, int width, int hight) 359254025Sjeff{ 360253685Sjeff int error; 361190620Skib 362190620Skib VGLMouseFreeze(dstx, dsty, width, hight, 0); 363190620Skib error = __VGLBitmapCopy(src, srcx, srcy, dst, dstx, dsty, width, hight); 364190620Skib VGLMouseUnFreeze(); 365190620Skib return error; 366190620Skib} 367190620Skib 368190620SkibVGLBitmap 369190620Skib*VGLBitmapCreate(int type, int xsize, int ysize, byte *bits) 370190620Skib{ 371190620Skib VGLBitmap *object; 372190620Skib 373190620Skib if (type != MEMBUF) 374190620Skib return NULL; 375190620Skib if (xsize < 0 || ysize < 0) 376190620Skib return NULL; 377190620Skib object = (VGLBitmap *)malloc(sizeof(*object)); 378190620Skib if (object == NULL) 379190620Skib return NULL; 380190620Skib object->Type = type; 381190620Skib object->Xsize = xsize; 382190620Skib object->Ysize = ysize; 383190620Skib object->VXsize = xsize; 384190620Skib object->VYsize = ysize; 385190620Skib object->Xorigin = 0; 386190620Skib object->Yorigin = 0; 387190620Skib object->Bitmap = bits; 388190620Skib return object; 389190620Skib} 390190620Skib 391190620Skibvoid 392190620SkibVGLBitmapDestroy(VGLBitmap *object) 393190620Skib{ 394190620Skib if (object->Bitmap) 395190620Skib free(object->Bitmap); 396190620Skib free(object); 397190620Skib} 398190620Skib 399190620Skibint 400190620SkibVGLBitmapAllocateBits(VGLBitmap *object) 401190620Skib{ 402190620Skib object->Bitmap = (byte *)malloc(object->VXsize*object->VYsize); 403190620Skib if (object->Bitmap == NULL) 404190620Skib return -1; 405190620Skib return 0; 406190620Skib} 407190620Skib