summaryrefslogtreecommitdiff
path: root/vgasrc
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2014-03-20 21:16:28 -0400
committerKevin O'Connor <kevin@koconnor.net>2014-04-11 11:26:22 -0400
commit7fd2af64225098a7819743fbe66f413d51929a69 (patch)
tree49cab281968a013b1b3e537a5919e4e8c8d50810 /vgasrc
parentefbf4d69038d6d5de05b80e0fffc7759b9e022fe (diff)
downloadqemu-seabios-7fd2af64225098a7819743fbe66f413d51929a69.tar.gz
vgabios: Split vgafb_scroll() into separate move and clear functions.
Rewrite the low-level scroll code so that it is implemented using two basic operations: move text and clear text. This simplifies the low-level code as it no longer needs to handle up scrolling vs down scrolling. Determining the direction of the scroll is now done in the higher level (vgabios.c) code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'vgasrc')
-rw-r--r--vgasrc/vgabios.c63
-rw-r--r--vgasrc/vgabios.h6
-rw-r--r--vgasrc/vgafb.c231
3 files changed, 178 insertions, 122 deletions
diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c
index 040a7ae..d0efc11 100644
--- a/vgasrc/vgabios.c
+++ b/vgasrc/vgabios.c
@@ -215,9 +215,20 @@ write_teletype(struct cursorpos *pcp, struct carattr ca)
u16 nbrows = GET_BDA(video_rows);
if (pcp->y > nbrows) {
pcp->y--;
- struct cursorpos ul = {0, 0, pcp->page};
- struct cursorpos lr = {GET_BDA(video_cols)-1, nbrows, pcp->page};
- vgafb_scroll(1, -1, ul, lr);
+
+ struct vgamode_s *vmode_g = get_current_mode();
+ if (!vmode_g)
+ return;
+
+ struct cursorpos dest = {0, 0, pcp->page};
+ struct cursorpos src = {0, 1, pcp->page};
+ struct cursorpos size = {GET_BDA(video_cols), nbrows};
+ vgafb_move_chars(vmode_g, dest, src, size);
+
+ struct cursorpos clr = {0, nbrows, pcp->page};
+ struct carattr attr = {' ', 0, 0};
+ struct cursorpos clrsize = {GET_BDA(video_cols), 1};
+ vgafb_clear_chars(vmode_g, clr, attr, clrsize);
}
}
@@ -415,18 +426,48 @@ verify_scroll(struct bregs *regs, int dir)
u16 nbcols = GET_BDA(video_cols);
if (lrx >= nbcols)
lrx = nbcols - 1;
-
- if (ulx > lrx || uly > lry)
+ int wincols = lrx - ulx + 1, winrows = lry - uly + 1;
+ if (wincols <= 0 || winrows <= 0)
return;
- int nblines = regs->al;
- if (!nblines || nblines > lry - uly + 1)
- nblines = lry - uly + 1;
+ struct vgamode_s *vmode_g = get_current_mode();
+ if (!vmode_g)
+ return;
u8 page = GET_BDA(video_page);
- struct cursorpos ul = {ulx, uly, page};
- struct cursorpos lr = {lrx, lry, page};
- vgafb_scroll(dir * nblines, regs->bh, ul, lr);
+ int clearlines = regs->al, movelines = winrows - clearlines;
+ if (!clearlines || movelines <= 0) {
+ // Clear whole area.
+ struct cursorpos clr = {ulx, uly, page};
+ struct carattr attr = {' ', regs->bh, 1};
+ struct cursorpos clrsize = {wincols, winrows};
+ vgafb_clear_chars(vmode_g, clr, attr, clrsize);
+ return;
+ }
+
+ if (dir > 0) {
+ // Normal scroll
+ struct cursorpos dest = {ulx, uly, page};
+ struct cursorpos src = {ulx, uly + clearlines, page};
+ struct cursorpos size = {wincols, movelines};
+ vgafb_move_chars(vmode_g, dest, src, size);
+
+ struct cursorpos clr = {ulx, uly + movelines, page};
+ struct carattr attr = {' ', regs->bh, 1};
+ struct cursorpos clrsize = {wincols, clearlines};
+ vgafb_clear_chars(vmode_g, clr, attr, clrsize);
+ } else {
+ // Scroll down
+ struct cursorpos dest = {ulx, uly + clearlines, page};
+ struct cursorpos src = {ulx, uly, page};
+ struct cursorpos size = {wincols, movelines};
+ vgafb_move_chars(vmode_g, dest, src, size);
+
+ struct cursorpos clr = {ulx, uly, page};
+ struct carattr attr = {' ', regs->bh, 1};
+ struct cursorpos clrsize = {wincols, clearlines};
+ vgafb_clear_chars(vmode_g, clr, attr, clrsize);
+ }
}
static void
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index 6949560..de6ae59 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -87,8 +87,10 @@ struct vgamode_s *get_current_mode(void);
int vga_set_mode(int mode, int flags);
// vgafb.c
-void vgafb_scroll(int nblines, int attr
- , struct cursorpos ul, struct cursorpos lr);
+void vgafb_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize);
+void vgafb_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos movesize);
void vgafb_write_char(struct cursorpos cp, struct carattr ca);
struct carattr vgafb_read_char(struct cursorpos cp);
void vgafb_write_pixel(u8 color, u16 x, u16 y);
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index 7c2570f..5a2c4c8 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -17,12 +17,16 @@
* Screen scrolling
****************************************************************/
-static inline void *
-memcpy_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
+static inline void
+memmove_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
{
+ if (src < dst) {
+ dst += stride * (lines - 1);
+ src += stride * (lines - 1);
+ stride = -stride;
+ }
for (; lines; lines--, dst+=stride, src+=stride)
memcpy_far(seg, dst, seg, src, copylen);
- return dst;
}
static inline void
@@ -40,163 +44,172 @@ memset16_stride(u16 seg, void *dst, u16 val, int setlen, int stride, int lines)
}
static void
-scroll_pl4(struct vgamode_s *vmode_g, int nblines, int attr
- , struct cursorpos ul, struct cursorpos lr)
+planar_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize)
{
if (!CONFIG_VGA_STDVGA_PORTS)
return;
int cheight = GET_BDA(char_height);
int cwidth = 1;
int stride = GET_BDA(video_cols) * cwidth;
- void *src_far, *dest_far;
- if (nblines >= 0) {
- dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far + nblines * cheight * stride;
- } else {
- // Scroll down
- nblines = -nblines;
- dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far - nblines * cheight * stride;
- stride = -stride;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ void *src_far = (void*)(src.y * cheight * stride + src.x * cwidth);
+ int i;
+ for (i=0; i<4; i++) {
+ stdvga_planar4_plane(i);
+ memmove_stride(SEG_GRAPH, dest_far, src_far
+ , movesize.x * cwidth, stride, movesize.y * cheight);
}
- if (attr < 0)
- attr = 0;
- int cols = lr.x - ul.x + 1;
- int rows = lr.y - ul.y + 1;
+ stdvga_planar4_plane(-1);
+}
+
+static void
+planar_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos clearsize)
+{
+ if (!CONFIG_VGA_STDVGA_PORTS)
+ return;
+ int cheight = GET_BDA(char_height);
+ int cwidth = 1;
+ int stride = GET_BDA(video_cols) * cwidth;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
int i;
for (i=0; i<4; i++) {
stdvga_planar4_plane(i);
- void *dest = dest_far;
- if (nblines < rows)
- dest = memcpy_stride(SEG_GRAPH, dest, src_far, cols * cwidth
- , stride, (rows - nblines) * cheight);
- u8 pixels = (attr & (1<<i)) ? 0xff : 0x00;
- memset_stride(SEG_GRAPH, dest, pixels, cols * cwidth
- , stride, nblines * cheight);
+ u8 attr = (ca.attr & (1<<i)) ? 0xff : 0x00;
+ memset_stride(SEG_GRAPH, dest_far, attr
+ , clearsize.x * cwidth, stride, clearsize.y * cheight);
}
stdvga_planar4_plane(-1);
}
static void
-scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr
- , struct cursorpos ul, struct cursorpos lr)
+cga_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize)
{
int cheight = GET_BDA(char_height) / 2;
int cwidth = GET_GLOBAL(vmode_g->depth);
int stride = GET_BDA(video_cols) * cwidth;
- void *src_far, *dest_far;
- if (nblines >= 0) {
- dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far + nblines * cheight * stride;
- } else {
- // Scroll down
- nblines = -nblines;
- dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far - nblines * cheight * stride;
- stride = -stride;
- }
- if (attr < 0)
- attr = 0;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ void *src_far = (void*)(src.y * cheight * stride + src.x * cwidth);
+ memmove_stride(SEG_CTEXT, dest_far, src_far
+ , movesize.x * cwidth, stride, movesize.y * cheight);
+ memmove_stride(SEG_CTEXT, dest_far + 0x2000, src_far + 0x2000
+ , movesize.x * cwidth, stride, movesize.y * cheight);
+}
+
+static void
+cga_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos clearsize)
+{
+ int cheight = GET_BDA(char_height) / 2;
+ int cwidth = GET_GLOBAL(vmode_g->depth);
+ int stride = GET_BDA(video_cols) * cwidth;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ u8 attr = ca.attr;
if (cwidth == 1)
attr = (attr&1) | ((attr&1)<<1);
attr &= 3;
attr |= (attr<<2) | (attr<<4) | (attr<<6);
- int cols = lr.x - ul.x + 1;
- int rows = lr.y - ul.y + 1;
- if (nblines < rows) {
- memcpy_stride(SEG_CTEXT, dest_far+0x2000, src_far+0x2000, cols * cwidth
- , stride, (rows - nblines) * cheight);
- dest_far = memcpy_stride(SEG_CTEXT, dest_far, src_far, cols * cwidth
- , stride, (rows - nblines) * cheight);
- }
- memset_stride(SEG_CTEXT, dest_far + 0x2000, attr, cols * cwidth
- , stride, nblines * cheight);
- memset_stride(SEG_CTEXT, dest_far, attr, cols * cwidth
- , stride, nblines * cheight);
+ memset_stride(SEG_CTEXT, dest_far, attr
+ , clearsize.x * cwidth, stride, clearsize.y * cheight);
+ memset_stride(SEG_CTEXT, dest_far + 0x2000, attr
+ , clearsize.x * cwidth, stride, clearsize.y * cheight);
}
static void
-scroll_lin(struct vgamode_s *vmode_g, int nblines, int attr
- , struct cursorpos ul, struct cursorpos lr)
+packed_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize)
{
int cheight = GET_BDA(char_height);
int cwidth = 8;
int stride = GET_BDA(video_cols) * cwidth;
- void *src_far, *dest_far;
- if (nblines >= 0) {
- dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far + nblines * cheight * stride;
- } else {
- // Scroll down
- nblines = -nblines;
- dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
- src_far = dest_far - nblines * cheight * stride;
- stride = -stride;
- }
- if (attr < 0)
- attr = 0;
- int cols = lr.x - ul.x + 1;
- int rows = lr.y - ul.y + 1;
- if (nblines < rows)
- dest_far = memcpy_stride(SEG_GRAPH, dest_far, src_far, cols * cwidth
- , stride, (rows - nblines) * cheight);
- memset_stride(SEG_GRAPH, dest_far, attr, cols * cwidth
- , stride, nblines * cheight);
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ void *src_far = (void*)(src.y * cheight * stride + src.x * cwidth);
+ memmove_stride(SEG_GRAPH, dest_far, src_far
+ , movesize.x * cwidth, stride, movesize.y * cheight);
}
static void
-scroll_text(struct vgamode_s *vmode_g, int nblines, int attr
- , struct cursorpos ul, struct cursorpos lr)
+packed_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos clearsize)
+{
+ int cheight = GET_BDA(char_height);
+ int cwidth = 8;
+ int stride = GET_BDA(video_cols) * cwidth;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ memset_stride(SEG_GRAPH, dest_far, ca.attr
+ , clearsize.x * cwidth, stride, clearsize.y * cheight);
+}
+
+static void
+text_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize)
{
int cheight = 1;
int cwidth = 2;
int stride = GET_BDA(video_cols) * cwidth;
- void *src_far, *dest_far = (void*)(GET_BDA(video_pagesize) * ul.page);
- if (nblines >= 0) {
- dest_far += ul.y * cheight * stride + ul.x * cwidth;
- src_far = dest_far + nblines * cheight * stride;
- } else {
- // Scroll down
- nblines = -nblines;
- dest_far += lr.y * cheight * stride + ul.x * cwidth;
- src_far = dest_far - nblines * cheight * stride;
- stride = -stride;
- }
- if (attr < 0)
- attr = 0x07;
- attr = (attr << 8) | ' ';
- int cols = lr.x - ul.x + 1;
- int rows = lr.y - ul.y + 1;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ void *src_far = (void*)(src.y * cheight * stride + src.x * cwidth);
+ u32 pageoffset = GET_BDA(video_pagesize) * dest.page;
+ u16 seg = GET_GLOBAL(vmode_g->sstart);
+ memmove_stride(seg, dest_far + pageoffset, src_far + pageoffset
+ , movesize.x * cwidth, stride, movesize.y * cheight);
+}
+
+static void
+text_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos clearsize)
+{
+ int cheight = 1;
+ int cwidth = 2;
+ int stride = GET_BDA(video_cols) * cwidth;
+ void *dest_far = (void*)(dest.y * cheight * stride + dest.x * cwidth);
+ u16 attr = ((ca.use_attr ? ca.attr : 0x07) << 8) | ca.car;
+ u32 pageoffset = GET_BDA(video_pagesize) * dest.page;
u16 seg = GET_GLOBAL(vmode_g->sstart);
- if (nblines < rows)
- dest_far = memcpy_stride(seg, dest_far, src_far, cols * cwidth
- , stride, (rows - nblines) * cheight);
- memset16_stride(seg, dest_far, attr, cols * cwidth
- , stride, nblines * cheight);
+ memset16_stride(seg, dest_far + pageoffset, attr
+ , clearsize.x * cwidth, stride, clearsize.y * cheight);
}
void
-vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
+vgafb_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct cursorpos src, struct cursorpos movesize)
{
- // Get the mode
- struct vgamode_s *vmode_g = get_current_mode();
- if (!vmode_g)
- return;
+ switch (GET_GLOBAL(vmode_g->memmodel)) {
+ case MM_TEXT:
+ text_move_chars(vmode_g, dest, src, movesize);
+ break;
+ case MM_PLANAR:
+ planar_move_chars(vmode_g, dest, src, movesize);
+ break;
+ case MM_CGA:
+ cga_move_chars(vmode_g, dest, src, movesize);
+ break;
+ case MM_PACKED:
+ packed_move_chars(vmode_g, dest, src, movesize);
+ break;
+ default:
+ break;
+ }
+}
- // FIXME gfx mode not complete
+void
+vgafb_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
+ , struct carattr ca, struct cursorpos movesize)
+{
switch (GET_GLOBAL(vmode_g->memmodel)) {
case MM_TEXT:
- scroll_text(vmode_g, nblines, attr, ul, lr);
+ text_clear_chars(vmode_g, dest, ca, movesize);
break;
case MM_PLANAR:
- scroll_pl4(vmode_g, nblines, attr, ul, lr);
+ planar_clear_chars(vmode_g, dest, ca, movesize);
break;
case MM_CGA:
- scroll_cga(vmode_g, nblines, attr, ul, lr);
+ cga_clear_chars(vmode_g, dest, ca, movesize);
break;
- case MM_DIRECT:
case MM_PACKED:
- scroll_lin(vmode_g, nblines, attr, ul, lr);
+ packed_clear_chars(vmode_g, dest, ca, movesize);
break;
default:
break;