Created
August 16, 2014 02:07
-
-
Save uobikiemukot/813b0df3810dc1f84335 to your computer and use it in GitHub Desktop.
yaft: patch for vga16fb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/draw.h b/draw.h | |
index 541688d..8a9b710 100644 | |
--- a/draw.h | |
+++ b/draw.h | |
@@ -1,24 +1,11 @@ | |
/* See LICENSE for licence details. */ | |
-static inline void draw_sixel(struct framebuffer *fb, int line, int col, uint8_t *pixmap) | |
-{ | |
- int h, w, src_offset, dst_offset; | |
- uint32_t pixel, color = 0; | |
- | |
- for (h = 0; h < CELL_HEIGHT; h++) { | |
- for (w = 0; w < CELL_WIDTH; w++) { | |
- src_offset = BYTES_PER_PIXEL * (h * CELL_WIDTH + w); | |
- memcpy(&color, pixmap + src_offset, BYTES_PER_PIXEL); | |
- | |
- dst_offset = (line * CELL_HEIGHT + h) * fb->line_length + (col * CELL_WIDTH + w) * fb->bytes_per_pixel; | |
- pixel = color2pixel(&fb->vinfo, color); | |
- memcpy(fb->buf + dst_offset, &pixel, fb->bytes_per_pixel); | |
- } | |
- } | |
-} | |
+enum { | |
+ VGA16_COLORS = 16, | |
+}; | |
static inline void draw_line(struct framebuffer *fb, struct terminal *term, int line) | |
{ | |
- int pos, size, bdf_padding, glyph_width, margin_right; | |
+ int pos, bdf_padding, glyph_width, margin_right; | |
int col, w, h; | |
uint32_t pixel; | |
struct color_pair_t color_pair; | |
@@ -31,10 +18,8 @@ static inline void draw_line(struct framebuffer *fb, struct terminal *term, int | |
cellp = &term->cells[line][col]; | |
/* draw sixel pixmap */ | |
- if (cellp->has_pixmap) { | |
- draw_sixel(fb, line, col, cellp->pixmap); | |
- continue; | |
- } | |
+ if (cellp->has_pixmap) | |
+ continue; /* not supported */ | |
/* copy current color_pair (maybe changed) */ | |
color_pair = cellp->color_pair; | |
@@ -60,14 +45,13 @@ static inline void draw_line(struct framebuffer *fb, struct terminal *term, int | |
color_pair.bg = color_pair.fg; | |
for (w = 0; w < CELL_WIDTH; w++) { | |
- pos = (term->width - 1 - margin_right - w) * fb->bytes_per_pixel | |
- + (line * CELL_HEIGHT + h) * fb->line_length; | |
+ /* fb->bytes_per_pixel must be 1 */ | |
+ pos = (line * CELL_HEIGHT + h) * fb->width | |
+ + (term->width - 1 - margin_right - w); | |
/* set color palette */ | |
if (cellp->glyphp->bitmap[h] & (0x01 << (bdf_padding + w))) | |
pixel = term->color_palette[color_pair.fg]; | |
- else if (fb->wall && color_pair.bg == DEFAULT_BG) /* wallpaper */ | |
- memcpy(&pixel, fb->wall + pos, fb->bytes_per_pixel); | |
else | |
pixel = term->color_palette[color_pair.bg]; | |
@@ -77,17 +61,33 @@ static inline void draw_line(struct framebuffer *fb, struct terminal *term, int | |
} | |
} | |
- /* actual display update (bit blit) */ | |
- pos = (line * CELL_HEIGHT) * fb->line_length; | |
- size = CELL_HEIGHT * fb->line_length; | |
- memcpy(fb->fp + pos, fb->buf + pos, size); | |
- | |
- /* TODO: page flip | |
- if fb_fix_screeninfo.ypanstep > 0, we can use hardware panning. | |
- set fb_fix_screeninfo.{yres_virtual,yoffset} and call ioctl(FBIOPAN_DISPLAY) | |
- but drivers of recent hardware (inteldrmfb, nouveaufb, radeonfb) don't support... | |
- (maybe we can use this by using libdrm) */ | |
- /* TODO: vertical synchronizing */ | |
+ /* actual display update */ | |
+ uint8_t mask[VGA16_COLORS], color; | |
+ int b, c, src_offset, dst_offset; | |
+ for (h = 0; h < CELL_HEIGHT; h++) { | |
+ for (w = 0; w < fb->width; w += BITS_PER_BYTE) { | |
+ memset(mask, 0, VGA16_COLORS * sizeof(uint8_t)); | |
+ src_offset = (line * CELL_HEIGHT + h) * fb->width + w; | |
+ dst_offset = (line * CELL_HEIGHT + h) * fb->line_length + w / BITS_PER_BYTE; | |
+ | |
+ for (b = 0; b < BITS_PER_BYTE; b++) { | |
+ color = *(fb->buf + src_offset + b) % VGA16_COLORS; | |
+ fprintf(stderr, "color index:%d\n", color); | |
+ /* left top pixel is MSBit of first byte */ | |
+ mask[color] |= 0x80 >> b; | |
+ //mask[color] |= 0x01 << b; | |
+ } | |
+ for (c = 0; c < VGA16_COLORS; c++) { | |
+ fprintf(stderr, "color mask:0x%.2X\n", mask[c]); | |
+ if (mask[c]) { | |
+ vga16_set_color(c); | |
+ vga16_select_mask(); | |
+ vga16_set_mask((int) mask[c]); | |
+ vga16_rmw(fb->fp + dst_offset); | |
+ } | |
+ } | |
+ } | |
+ } | |
term->line_dirty[line] = ((term->mode & MODE_CURSOR) && term->cursor.y == line) ? true: false; | |
} | |
diff --git a/fb/linux.h b/fb/linux.h | |
index 19ea68e..39961cb 100644 | |
--- a/fb/linux.h | |
+++ b/fb/linux.h | |
@@ -7,7 +7,6 @@ | |
struct framebuffer { | |
uint8_t *fp; /* pointer of framebuffer (read only) */ | |
uint8_t *buf; /* copy of framebuffer */ | |
- uint8_t *wall; /* buffer for wallpaper */ | |
int fd; /* file descriptor of framebuffer */ | |
int width, height; /* display resolution */ | |
long screen_size; /* screen data size (byte) */ | |
@@ -17,17 +16,6 @@ struct framebuffer { | |
struct fb_var_screeninfo vinfo; | |
}; | |
-/* common functions */ | |
-uint8_t *load_wallpaper(struct framebuffer *fb) | |
-{ | |
- uint8_t *ptr; | |
- | |
- ptr = (uint8_t *) ecalloc(1, fb->screen_size); | |
- memcpy(ptr, fb->fp, fb->screen_size); | |
- | |
- return ptr; | |
-} | |
- | |
/* some functions for Linux framebuffer */ | |
void cmap_create(struct fb_cmap **cmap) | |
{ | |
@@ -131,7 +119,7 @@ static inline uint32_t color2pixel(struct fb_var_screeninfo *vinfo, uint32_t col | |
void fb_init(struct framebuffer *fb, uint32_t *color_palette) | |
{ | |
int i; | |
- char *path, *env; | |
+ char *path; | |
struct fb_fix_screeninfo finfo; | |
struct fb_var_screeninfo vinfo; | |
@@ -169,7 +157,19 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette) | |
cmap_init(fb, &vinfo); | |
fb->bytes_per_pixel = 1; | |
} | |
- else /* non packed pixel, mono color, grayscale: not implimented */ | |
+ else if (finfo.type == FB_TYPE_VGA_PLANES && finfo.visual == FB_VISUAL_PSEUDOCOLOR) { | |
+ /* set ega/vga port permission */ | |
+ if (ioperm(0x3C0, 0x20, 1)) | |
+ fatal("ioperm failed"); | |
+ | |
+ vga16_set_enable_sr(0x0F); | |
+ vga16_set_op(0); | |
+ vga16_set_mode(0); | |
+ | |
+ fb->cmap = fb->cmap_org = NULL; | |
+ fb->bytes_per_pixel = 1; /* bpp of backbuffer */ | |
+ } | |
+ else | |
fatal("unsupported framebuffer type"); | |
for (i = 0; i < COLORS; i++) /* init color palette */ | |
@@ -177,13 +177,7 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette) | |
fb->fp = (uint8_t *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0); | |
fb->buf = (uint8_t *) ecalloc(1, fb->screen_size); | |
- //fb->wall = (WALLPAPER && fb->bytes_per_pixel > 1) ? load_wallpaper(fb): NULL; | |
fb->vinfo = vinfo; | |
- | |
- if (((env = getenv("YAFT")) != NULL) && (strstr(env, "wall") != NULL)) | |
- fb->wall = load_wallpaper(fb); | |
- else | |
- fb->wall = NULL; | |
} | |
void fb_die(struct framebuffer *fb) | |
@@ -194,7 +188,6 @@ void fb_die(struct framebuffer *fb) | |
cmap_die(fb->cmap_org); | |
} | |
free(fb->buf); | |
- free(fb->wall); | |
emunmap(fb->fp, fb->screen_size); | |
eclose(fb->fd); | |
} | |
diff --git a/vga16.h b/vga16.h | |
new file mode 100644 | |
index 0000000..8aa1abd | |
--- /dev/null | |
+++ b/vga16.h | |
@@ -0,0 +1,72 @@ | |
+/* See LICENSE for licence details. */ | |
+#include <sys/io.h> | |
+ | |
+enum { | |
+ GRAPHICS_ADDR_REG = 0x3ce, /* Graphics address register. */ | |
+ GRAPHICS_DATA_REG = 0x3cf, /* Graphics data register. */ | |
+}; | |
+ | |
+/* Program the Set/Reset Register for drawing in color COLOR for write | |
+ mode 0. */ | |
+static inline void vga16_set_color(int c) | |
+{ | |
+ outb(0, GRAPHICS_ADDR_REG); | |
+ outb(c, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Set the Enable Set/Reset Register. */ | |
+static inline void vga16_set_enable_sr(int mask) | |
+{ | |
+ outb(1, GRAPHICS_ADDR_REG); | |
+ outb(mask, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Select the Bit Mask Register on the Graphics Controller. */ | |
+static inline void vga16_select_mask(void) | |
+{ | |
+ outb(8, GRAPHICS_ADDR_REG); | |
+} | |
+ | |
+/* Program the Bit Mask Register to affect only the pixels selected in | |
+ MASK. The Bit Mask Register must already have been selected with | |
+ select_mask(). */ | |
+static inline void vga16_set_mask(int mask) | |
+{ | |
+ outb(mask, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Set the Data Rotate Register. Bits 0-2 are rotate count, bits 3-4 | |
+ are logical operation(0=NOP, 1=AND, 2=OR, 3=XOR). */ | |
+static inline void vga16_set_op(int op) | |
+{ | |
+ outb(3, GRAPHICS_ADDR_REG); | |
+ outb(op, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Set the Memory Plane Write Enable register. */ | |
+static inline void vga16_set_write_planes(int mask) | |
+{ | |
+ outb(2, 0x3c4); | |
+ outb(mask, 0x3c5); | |
+} | |
+ | |
+/* Set the Read Map Select register. */ | |
+static inline void vga16_set_read_plane(int plane) | |
+{ | |
+ outb(4, GRAPHICS_ADDR_REG); | |
+ outb(plane, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Set the Graphics Mode Register. The write mode is in bits 0-1, the | |
+ read mode is in bit 3. */ | |
+static inline void vga16_set_mode(int mode) | |
+{ | |
+ outb(5, GRAPHICS_ADDR_REG); | |
+ outb(mode, GRAPHICS_DATA_REG); | |
+} | |
+ | |
+/* Read-modify-write the specified memory byte. */ | |
+static inline void vga16_rmw(volatile uint8_t *p) | |
+{ | |
+ *p |= 1; | |
+} | |
diff --git a/yaft.c b/yaft.c | |
index 6068da2..ad21356 100644 | |
--- a/yaft.c | |
+++ b/yaft.c | |
@@ -3,17 +3,10 @@ | |
#include "conf.h" | |
#include "util.h" | |
-#if defined(__linux__) | |
- #include "fb/linux.h" | |
-#elif defined(__FreeBSD__) | |
- #include "fb/freebsd.h" | |
-#elif defined(__NetBSD__) | |
- #include "fb/netbsd.h" | |
-#elif defined(__OpenBSD__) | |
- #include "fb/openbsd.h" | |
-#endif | |
- | |
+#include "vga16.h" | |
+#include "fb/linux.h" | |
#include "draw.h" | |
+ | |
#include "terminal.h" | |
#include "function.h" | |
#include "osc.h" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment