diff options
Diffstat (limited to 'lib/libvgl/bitmap.c')
-rw-r--r-- | lib/libvgl/bitmap.c | 207 |
1 files changed, 170 insertions, 37 deletions
diff --git a/lib/libvgl/bitmap.c b/lib/libvgl/bitmap.c index e66150c..2714e89 100644 --- a/lib/libvgl/bitmap.c +++ b/lib/libvgl/bitmap.c @@ -30,9 +30,11 @@ #include <sys/types.h> #include <signal.h> +#include <machine/console.h> #include "vgl.h" -static byte VGLPlane[4][128]; +#define min(x, y) (((x) < (y)) ? (x) : (y)) + static byte mask[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; static int color2bit[16] = {0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, @@ -43,20 +45,28 @@ static void WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) { int i, pos, last, planepos, start_offset, end_offset, offset; + int len; unsigned int word = 0; byte *address; + byte *VGLPlane[4]; switch (dst->Type) { case VIDBUF4: - address = dst->Bitmap + (dst->Xsize/8 * y) + x/8; + case VIDBUF4S: start_offset = (x & 0x07); end_offset = (x + width) & 0x07; - offset = start_offset; + i = (width + start_offset) / 8; + if (end_offset) + i++; + VGLPlane[0] = VGLBuf; + VGLPlane[1] = VGLPlane[0] + i; + VGLPlane[2] = VGLPlane[1] + i; + VGLPlane[3] = VGLPlane[2] + i; pos = 0; planepos = 0; + last = 8 - start_offset; while (pos < width) { word = 0; - last = pos + 8 - offset; while (pos < last && pos < width) word = (word<<1) | color2bit[line[pos++]&0x0f]; VGLPlane[0][planepos] = word; @@ -64,7 +74,7 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) VGLPlane[2][planepos] = word>>16; VGLPlane[3][planepos] = word>>24; planepos++; - offset = 0; + last += 8; } planepos--; if (end_offset) { @@ -76,20 +86,43 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) } if (start_offset || end_offset) width+=8; + width /= 8; + outb(0x3ce, 0x01); outb(0x3cf, 0x00); /* set/reset enable */ + outb(0x3ce, 0x08); outb(0x3cf, 0xff); /* bit mask */ for (i=0; i<4; i++) { outb(0x3c4, 0x02); outb(0x3c5, 0x01<<i); outb(0x3ce, 0x04); outb(0x3cf, i); - if (start_offset) - VGLPlane[i][0] |= *address & ~mask[start_offset]; - if (end_offset) - VGLPlane[i][planepos] |= *(address + planepos) & mask[end_offset]; - bcopy(&VGLPlane[i][0], address, width/8); + pos = VGLAdpInfo.va_line_width*y + x/8; + if (dst->Type == VIDBUF4) { + if (end_offset) + VGLPlane[i][planepos] |= dst->Bitmap[pos+planepos] & mask[end_offset]; + if (start_offset) + VGLPlane[i][0] |= dst->Bitmap[pos] & ~mask[start_offset]; + bcopy(&VGLPlane[i][0], dst->Bitmap + pos, width); + } else { /* VIDBUF4S */ + if (end_offset) { + offset = VGLSetSegment(pos + planepos); + VGLPlane[i][planepos] |= dst->Bitmap[offset] & mask[end_offset]; + } + offset = VGLSetSegment(pos); + if (start_offset) + VGLPlane[i][0] |= dst->Bitmap[offset] & ~mask[start_offset]; + for (last = width; ; ) { + len = min(VGLAdpInfo.va_window_size - offset, last); + bcopy(&VGLPlane[i][width - last], dst->Bitmap + offset, len); + pos += len; + last -= len; + if (last <= 0) + break; + offset = VGLSetSegment(pos); + } + } } break; case VIDBUF8X: - address = dst->Bitmap + (dst->Xsize/2 * y) + x/4; + address = dst->Bitmap + VGLAdpInfo.va_line_width * y + x/4; for (i=0; i<4; i++) { outb(0x3c4, 0x02); outb(0x3c5, 0x01 << ((x + i)%4)); @@ -99,9 +132,20 @@ WriteVerticalLine(VGLBitmap *dst, int x, int y, int width, byte *line) ++address; } break; + case VIDBUF8S: + pos = dst->VXsize * y + x; + while (width > 0) { + offset = VGLSetSegment(pos); + i = min(VGLAdpInfo.va_window_size - offset, width); + bcopy(line, dst->Bitmap + offset, i); + line += i; + pos += i; + width -= i; + } + break; case VIDBUF8: case MEMBUF: - address = dst->Bitmap + (dst->Xsize * y) + x; + address = dst->Bitmap + dst->VXsize * y + x; bcopy(line, address, width); break; @@ -113,40 +157,67 @@ static void ReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line) { int i, bit, pos, count, planepos, start_offset, end_offset, offset; + int width2, len; byte *address; + byte *VGLPlane[4]; switch (src->Type) { + case VIDBUF4S: + start_offset = (x & 0x07); + end_offset = (x + width) & 0x07; + count = (width + start_offset) / 8; + if (end_offset) + count++; + VGLPlane[0] = VGLBuf; + VGLPlane[1] = VGLPlane[0] + count; + VGLPlane[2] = VGLPlane[1] + count; + VGLPlane[3] = VGLPlane[2] + count; + for (i=0; i<4; i++) { + outb(0x3ce, 0x04); + outb(0x3cf, i); + pos = VGLAdpInfo.va_line_width*y + x/8; + for (width2 = count; width2 > 0; ) { + offset = VGLSetSegment(pos); + len = min(VGLAdpInfo.va_window_size - offset, width2); + bcopy(src->Bitmap + offset, &VGLPlane[i][count - width2], len); + pos += len; + width2 -= len; + } + } + goto read_planar; case VIDBUF4: - address = src->Bitmap + (src->Xsize/8 * y) + x/8; + address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/8; start_offset = (x & 0x07); end_offset = (x + width) & 0x07; - offset = start_offset; - if (start_offset) - count = (width - (8 - start_offset)) / 8 + 1; - else - count = width / 8; + count = (width + start_offset) / 8; if (end_offset) - count++; + count++; + VGLPlane[0] = VGLBuf; + VGLPlane[1] = VGLPlane[0] + count; + VGLPlane[2] = VGLPlane[1] + count; + VGLPlane[3] = VGLPlane[2] + count; for (i=0; i<4; i++) { outb(0x3ce, 0x04); outb(0x3cf, i); bcopy(address, &VGLPlane[i][0], count); } +read_planar: pos = 0; planepos = 0; + bit = 7 - start_offset; while (pos < width) { - for (bit = (7-offset); bit >= 0 && pos < width; bit--, pos++) { + for (; bit >= 0 && pos < width; bit--, pos++) { line[pos] = (VGLPlane[0][planepos] & (1<<bit) ? 1 : 0) | ((VGLPlane[1][planepos] & (1<<bit) ? 1 : 0) << 1) | ((VGLPlane[2][planepos] & (1<<bit) ? 1 : 0) << 2) | ((VGLPlane[3][planepos] & (1<<bit) ? 1 : 0) << 3); } planepos++; - offset = 0; + bit = 7; } break; case VIDBUF8X: - address = src->Bitmap + (src->Xsize/2 * y) + x/4; + address = src->Bitmap + VGLAdpInfo.va_line_width * y + x/4; for (i=0; i<4; i++) { outb(0x3ce, 0x04); outb(0x3cf, (x + i)%4); @@ -156,9 +227,20 @@ ReadVerticalLine(VGLBitmap *src, int x, int y, int width, byte *line) ++address; } break; + case VIDBUF8S: + pos = src->VXsize * y + x; + while (width > 0) { + offset = VGLSetSegment(pos); + i = min(VGLAdpInfo.va_window_size - offset, width); + bcopy(src->Bitmap + offset, line, i); + line += i; + pos += i; + width -= i; + } + break; case VIDBUF8: case MEMBUF: - address = src->Bitmap + (src->Xsize * y) + x; + address = src->Bitmap + src->VXsize * y + x; bcopy(address, line, width); break; default: @@ -171,7 +253,8 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, { int srcline, dstline; - if (srcx>src->Xsize||srcy>src->Ysize||dstx>dst->Xsize||dsty>dst->Ysize) + if (srcx>src->VXsize || srcy>src->VYsize + || dstx>dst->VXsize || dsty>dst->VYsize) return -1; if (srcx < 0) { width=width+srcx; dstx-=srcx; srcx=0; @@ -185,34 +268,45 @@ __VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, if (dsty < 0) { hight=hight+dsty; srcy-=dsty; dsty=0; } - if (srcx+width > src->Xsize) - width=src->Xsize-srcx; - if (srcy+hight > src->Ysize) - hight=src->Ysize-srcy; - if (dstx+width > dst->Xsize) - width=dst->Xsize-dstx; - if (dsty+hight > dst->Ysize) - hight=dst->Ysize-dsty; + if (srcx+width > src->VXsize) + width=src->VXsize-srcx; + if (srcy+hight > src->VYsize) + hight=src->VYsize-srcy; + if (dstx+width > dst->VXsize) + width=dst->VXsize-dstx; + if (dsty+hight > dst->VYsize) + hight=dst->VYsize-dsty; if (width < 0 || hight < 0) return -1; if (src->Type == MEMBUF) { for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { WriteVerticalLine(dst, dstx, dstline, width, - (src->Bitmap+(srcline*src->Xsize)+srcx)); + (src->Bitmap+(srcline*src->VXsize)+srcx)); } } else if (dst->Type == MEMBUF) { for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { ReadVerticalLine(src, srcx, srcline, width, - (dst->Bitmap+(dstline*dst->Xsize)+dstx)); + (dst->Bitmap+(dstline*dst->VXsize)+dstx)); } } else { - byte buffer[1024]; + byte buffer[2048]; /* XXX */ + byte *p; + + if (width > sizeof(buffer)) { + p = malloc(width); + if (p == NULL) + return 1; + } else { + p = buffer; + } for (srcline=srcy, dstline=dsty; srcline<srcy+hight; srcline++, dstline++) { - ReadVerticalLine(src, srcx, srcline, width, buffer); - WriteVerticalLine(dst, dstx, dstline, width, buffer); + ReadVerticalLine(src, srcx, srcline, width, p); + WriteVerticalLine(dst, dstx, dstline, width, p); } + if (width > sizeof(buffer)) + free(p); } return 0; } @@ -229,3 +323,42 @@ VGLBitmapCopy(VGLBitmap *src, int srcx, int srcy, return error; } +VGLBitmap +*VGLBitmapCreate(int type, int xsize, int ysize, byte *bits) +{ + VGLBitmap *object; + + if (type != MEMBUF) + return NULL; + if (xsize < 0 || ysize < 0) + return NULL; + object = (VGLBitmap *)malloc(sizeof(*object)); + if (object == NULL) + return NULL; + object->Type = type; + object->Xsize = xsize; + object->Ysize = ysize; + object->VXsize = xsize; + object->VYsize = ysize; + object->Xorigin = 0; + object->Yorigin = 0; + object->Bitmap = bits; + return object; +} + +void +VGLBitmapDestroy(VGLBitmap *object) +{ + if (object->Bitmap) + free(object->Bitmap); + free(object); +} + +int +VGLBitmapAllocateBits(VGLBitmap *object) +{ + object->Bitmap = (byte *)malloc(object->VXsize*object->VYsize); + if (object->Bitmap == NULL) + return -1; + return 0; +} |