aboutsummaryrefslogtreecommitdiffstats
path: root/fbtools.c
diff options
context:
space:
mode:
Diffstat (limited to 'fbtools.c')
-rw-r--r--fbtools.c148
1 files changed, 114 insertions, 34 deletions
diff --git a/fbtools.c b/fbtools.c
index e201951..49afb2c 100644
--- a/fbtools.c
+++ b/fbtools.c
@@ -34,8 +34,6 @@ static const char *strsignal(int signr)
/* -------------------------------------------------------------------- */
/* exported stuff */
-struct fb_fix_screeninfo fb_fix;
-struct fb_var_screeninfo fb_var;
unsigned char *fb_mem;
int fb_mem_offset = 0;
int fb_switch_state = FB_ACTIVE;
@@ -43,10 +41,10 @@ int fb_switch_state = FB_ACTIVE;
/* -------------------------------------------------------------------- */
/* internal variables */
+static struct fb_fix_screeninfo fb_fix;
+static struct fb_var_screeninfo fb_var;
+
static int fb,tty;
-#if 0
-static int bpp,black,white;
-#endif
static int orig_vt_no = 0;
static struct vt_mode vt_mode;
@@ -58,6 +56,9 @@ static struct fb_var_screeninfo fb_ovar;
static unsigned short ored[256], ogreen[256], oblue[256];
static struct fb_cmap ocmap = { 0, 256, ored, ogreen, oblue };
+static unsigned short p_red[256], p_green[256], p_blue[256];
+static struct fb_cmap p_cmap = { 0, 256, p_red, p_green, p_blue };
+
/* -------------------------------------------------------------------- */
/* devices */
@@ -92,6 +93,64 @@ static void dev_init(void)
}
/* -------------------------------------------------------------------- */
+/* palette handling */
+
+static unsigned short color_scale(int n, int max)
+{
+ int ret = 65535.0 * (float)n/(max);
+ if (ret > 65535) ret = 65535;
+ if (ret < 0) ret = 0;
+ return ret;
+}
+
+static void fb_linear_palette(int r, int g, int b)
+{
+ int i, size;
+
+ size = 256 >> (8 - r);
+ for (i = 0; i < size; i++)
+ p_red[i] = color_scale(i,size);
+ p_cmap.len = size;
+
+ size = 256 >> (8 - g);
+ for (i = 0; i < size; i++)
+ p_green[i] = color_scale(i,size);
+ if (p_cmap.len < size)
+ p_cmap.len = size;
+
+ size = 256 >> (8 - b);
+ for (i = 0; i < size; i++)
+ p_blue[i] = color_scale(i,size);
+ if (p_cmap.len < size)
+ p_cmap.len = size;
+}
+
+static void fb_dither_palette(int r, int g, int b)
+{
+ int rs, gs, bs, i;
+
+ rs = 256 / (r - 1);
+ gs = 256 / (g - 1);
+ bs = 256 / (b - 1);
+ for (i = 0; i < 256; i++) {
+ p_red[i] = color_scale(rs * ((i / (g * b)) % r), 255);
+ p_green[i] = color_scale(gs * ((i / b) % g), 255);
+ p_blue[i] = color_scale(bs * ((i) % b), 255);
+ }
+ p_cmap.len = 256;
+}
+
+static void fb_set_palette(void)
+{
+ if (fb_fix.visual != FB_VISUAL_DIRECTCOLOR && fb_var.bits_per_pixel != 8)
+ return;
+ if (-1 == ioctl(fb,FBIOPUTCMAP,&p_cmap)) {
+ perror("ioctl FBIOPUTCMAP");
+ exit(1);
+ }
+}
+
+/* -------------------------------------------------------------------- */
/* console switching */
extern int debug;
@@ -324,12 +383,18 @@ static int fb_activate_current(int tty)
return 0;
}
-int
-fb_init(char *device, char *mode, int vt)
+static void fb_restore_display(void)
+{
+ ioctl(fb,FBIOPAN_DISPLAY,&fb_var);
+ fb_set_palette();
+}
+
+gfxstate* fb_init(char *device, char *mode, int vt)
{
char fbdev[16];
struct vt_stat vts;
unsigned long page_mask;
+ gfxstate *gfx;
dev_init();
tty = 0;
@@ -406,32 +471,6 @@ fb_init(char *device, char *mode, int vt)
fprintf(stderr,"can handle only packed pixel frame buffers\n");
goto err;
}
-#if 0
- switch (fb_var.bits_per_pixel) {
- case 8:
- white = 255; black = 0; bpp = 1;
- break;
- case 15:
- case 16:
- if (fb_var.green.length == 6)
- white = 0xffff;
- else
- white = 0x7fff;
- black = 0; bpp = 2;
- break;
- case 24:
- white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;
- break;
- case 32:
- white = 0xffffff; black = 0; bpp = fb_var.bits_per_pixel/8;
- fb_setpixels = fb_setpixels4;
- break;
- default:
- fprintf(stderr, "Oops: %i bit/pixel ???\n",
- fb_var.bits_per_pixel);
- goto err;
- }
-#endif
page_mask = getpagesize()-1;
fb_mem_offset = (unsigned long)(fb_fix.smem_start) & page_mask;
fb_mem = mmap(NULL,fb_fix.smem_len+fb_mem_offset,
@@ -457,7 +496,48 @@ fb_init(char *device, char *mode, int vt)
/* cls */
fb_memset(fb_mem+fb_mem_offset, 0, fb_fix.line_length * fb_var.yres);
- return fb;
+
+ /* init palette */
+ switch (fb_var.bits_per_pixel) {
+ case 8:
+ fb_dither_palette(8, 8, 4);
+ break;
+ case 15:
+ case 16:
+ if (fb_var.green.length == 5) {
+ fb_linear_palette(5,5,5);
+ } else {
+ fb_linear_palette(5,6,5);
+ }
+ break;
+ case 24:
+ case 32:
+ fb_linear_palette(8,8,8);
+ break;
+ }
+ fb_set_palette();
+
+ /* prepare gfx */
+ gfx = malloc(sizeof(*gfx));
+ memset(gfx, 0, sizeof(*gfx));
+
+ gfx->hdisplay = fb_var.xres;
+ gfx->vdisplay = fb_var.yres;
+ gfx->stride = fb_fix.line_length;
+ gfx->rlen = fb_var.red.length;
+ gfx->glen = fb_var.green.length;
+ gfx->blen = fb_var.blue.length;
+ gfx->tlen = fb_var.transp.length;
+ gfx->roff = fb_var.red.offset;
+ gfx->goff = fb_var.green.offset;
+ gfx->boff = fb_var.blue.offset;
+ gfx->toff = fb_var.transp.offset;
+ gfx->bits_per_pixel = fb_var.bits_per_pixel;
+
+ gfx->restore_display = fb_restore_display;
+
+ gfx->fb_fd = fb;
+ return gfx;
err:
fb_cleanup();