diff options
-rw-r--r-- | fb-gui.c | 155 | ||||
-rw-r--r-- | fb-gui.h | 7 | ||||
-rw-r--r-- | fbi.c | 135 | ||||
-rw-r--r-- | fbiconfig.c | 6 | ||||
-rw-r--r-- | fbiconfig.h | 4 | ||||
-rw-r--r-- | fbtools.c | 148 | ||||
-rw-r--r-- | fbtools.h | 7 | ||||
-rw-r--r-- | gfx.h | 20 |
8 files changed, 225 insertions, 257 deletions
@@ -24,62 +24,11 @@ static int xs = 10; /* ---------------------------------------------------------------------- */ /* shadow framebuffer -- internals */ -static float p_gamma = 1; -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 }; - static int32_t s_lut_transp[256], s_lut_red[256], s_lut_green[256], s_lut_blue[256]; static unsigned char **shadow; static unsigned int *sdirty,swidth,sheight; -static unsigned short calc_gamma(int n, int max) -{ - int ret = 65535.0 * pow((float)n/(max), 1 / p_gamma); - if (ret > 65535) ret = 65535; - if (ret < 0) ret = 0; - return ret; -} - -static void -linear_palette(int r, int g, int b) -{ - int i, size; - - size = 256 >> (8 - r); - for (i = 0; i < size; i++) - p_red[i] = calc_gamma(i,size); - p_cmap.len = size; - - size = 256 >> (8 - g); - for (i = 0; i < size; i++) - p_green[i] = calc_gamma(i,size); - if (p_cmap.len < size) - p_cmap.len = size; - - size = 256 >> (8 - b); - for (i = 0; i < size; i++) - p_blue[i] = calc_gamma(i,size); - if (p_cmap.len < size) - p_cmap.len = size; -} - -static void -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] = calc_gamma(rs * ((i / (g * b)) % r), 255); - p_green[i] = calc_gamma(gs * ((i / b) % g), 255); - p_blue[i] = calc_gamma(bs * ((i) % b), 255); - } - p_cmap.len = 256; -} - static void shadow_lut_init_one(int32_t *lut, int bits, int shift) { int i; @@ -92,57 +41,23 @@ static void shadow_lut_init_one(int32_t *lut, int bits, int shift) lut[i] = (i >> (8 - bits)) << shift; } -static void shadow_lut_init(int depth) +static void shadow_lut_init(gfxstate *gfx) { - if (fb_var.red.length && - fb_var.green.length && - fb_var.blue.length) { - /* fb_var.{red|green|blue} looks sane, use it */ - shadow_lut_init_one(s_lut_transp, fb_var.transp.length, fb_var.transp.offset); - shadow_lut_init_one(s_lut_red, fb_var.red.length, fb_var.red.offset); - shadow_lut_init_one(s_lut_green, fb_var.green.length, fb_var.green.offset); - shadow_lut_init_one(s_lut_blue, fb_var.blue.length, fb_var.blue.offset); - } else { - /* fallback */ - int i; - switch (depth) { - case 15: - for (i = 0; i < 256; i++) { - s_lut_red[i] = (i & 0xf8) << 7; /* bits -rrrrr-- -------- */ - s_lut_green[i] = (i & 0xf8) << 2; /* bits ------gg ggg----- */ - s_lut_blue[i] = (i & 0xf8) >> 3; /* bits -------- ---bbbbb */ - } - break; - case 16: - for (i = 0; i < 256; i++) { - s_lut_red[i] = (i & 0xf8) << 8; /* bits rrrrr--- -------- */ - s_lut_green[i] = (i & 0xfc) << 3; /* bits -----ggg ggg----- */ - s_lut_blue[i] = (i & 0xf8) >> 3; /* bits -------- ---bbbbb */ - } - break; - case 32: - for (i = 0; i < 256; i++) { - s_lut_transp[i] = i << 24; /* byte a--- */ - } - case 24: - for (i = 0; i < 256; i++) { - s_lut_red[i] = i << 16; /* byte -r-- */ - s_lut_green[i] = i << 8; /* byte --g- */ - s_lut_blue[i] = i; /* byte ---b */ - } - break; - } - } + shadow_lut_init_one(s_lut_transp, gfx->tlen, gfx->toff); + shadow_lut_init_one(s_lut_red, gfx->rlen, gfx->roff); + shadow_lut_init_one(s_lut_green, gfx->glen, gfx->goff); + shadow_lut_init_one(s_lut_blue, gfx->blen, gfx->boff); } -static void shadow_render_line(int line, unsigned char *dest, char unsigned *buffer) +static void shadow_render_line(gfxstate *gfx, int line, + unsigned char *dest, char unsigned *buffer) { uint8_t *ptr = (void*)dest; uint16_t *ptr2 = (void*)dest; uint32_t *ptr4 = (void*)dest; int x; - switch (fb_var.bits_per_pixel) { + switch (gfx->bits_per_pixel) { case 8: dither_line(buffer, ptr, line, swidth); break; @@ -175,17 +90,17 @@ static void shadow_render_line(int line, unsigned char *dest, char unsigned *buf /* ---------------------------------------------------------------------- */ /* shadow framebuffer -- management interface */ -void shadow_render(void) +void shadow_render(gfxstate *gfx) { unsigned int offset = 0; int i; if (!visible) return; - for (i = 0; i < sheight; i++, offset += fb_fix.line_length) { + for (i = 0; i < sheight; i++, offset += gfx->stride) { if (0 == sdirty[i]) continue; - shadow_render_line(i, fb_mem + offset, shadow[i]); + shadow_render_line(gfx, i, fb_mem + offset, shadow[i]); sdirty[i] = 0; } } @@ -213,23 +128,13 @@ void shadow_set_dirty(void) sdirty[i]++; } -void shadow_set_palette(int fd) -{ - if (fb_fix.visual != FB_VISUAL_DIRECTCOLOR && fb_var.bits_per_pixel != 8) - return; - if (-1 == ioctl(fd,FBIOPUTCMAP,&p_cmap)) { - perror("ioctl FBIOPUTCMAP"); - exit(1); - } -} - -void shadow_init(void) +void shadow_init(gfxstate *gfx) { int i; /* init shadow fb */ - swidth = fb_var.xres; - sheight = fb_var.yres; + swidth = gfx->hdisplay; + sheight = gfx->vdisplay; shadow = malloc(sizeof(unsigned char*) * sheight); sdirty = malloc(sizeof(unsigned int) * sheight); memset(sdirty,0, sizeof(unsigned int) * sheight); @@ -238,36 +143,20 @@ void shadow_init(void) shadow_clear(); /* init rendering */ - switch (fb_var.bits_per_pixel) { + switch (gfx->bits_per_pixel) { case 8: - dither_palette(8, 8, 4); init_dither(8, 8, 4, 2); dither_line = dither_line_color; break; case 15: case 16: - if (fb_var.green.length == 5) { - shadow_lut_init(15); - if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR) - linear_palette(5,5,5); - } else { - shadow_lut_init(16); - if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR) - linear_palette(5,6,5); - } - break; case 24: - if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR) - linear_palette(8,8,8); - break; case 32: - if (fb_fix.visual == FB_VISUAL_DIRECTCOLOR) - linear_palette(8,8,8); - shadow_lut_init(24); + shadow_lut_init(gfx); break; default: fprintf(stderr, "Oops: %i bit/pixel ???\n", - fb_var.bits_per_pixel); + gfx->bits_per_pixel); exit(1); } } @@ -674,14 +563,8 @@ FT_Face font_open(char *fcname) /* ---------------------------------------------------------------------- */ /* clear screen (areas) */ -void fb_clear_mem(void) -{ - if (visible) - fb_memset(fb_mem,0,fb_fix.smem_len); -} - -void fb_clear_screen(void) +void fb_clear_screen(gfxstate *gfx) { if (visible) - fb_memset(fb_mem,0,fb_fix.line_length * fb_var.yres); + fb_memset(fb_mem,0,gfx->stride * gfx->vdisplay); } @@ -4,12 +4,12 @@ extern int visible; -void shadow_render(void); +void shadow_render(gfxstate *gfx); void shadow_clear_lines(int first, int last); void shadow_clear(void); void shadow_set_dirty(void); void shadow_set_palette(int fd); -void shadow_init(void); +void shadow_init(gfxstate *gfx); void shadow_fini(void); void shadow_draw_line(int x1, int x2, int y1,int y2); @@ -29,5 +29,4 @@ void shadow_draw_text_box(FT_Face face, int x, int y, int percent, void font_init(void); FT_Face font_open(char *fcname); -void fb_clear_mem(void); -void fb_clear_screen(void); +void fb_clear_screen(gfxstate *gfx); @@ -119,16 +119,17 @@ static struct ida_image *img; static int img_cnt, min_cnt = 2, max_cnt = 16; static int img_mem, max_mem_mb; +/* graphics interface */ +gfxstate *gfx; + /* framebuffer */ char *fbdev = NULL; char *fbmode = NULL; -int fd, switch_last, debug; +int switch_last, debug; unsigned short red[256], green[256], blue[256]; struct fb_cmap cmap = { 0, 256, red, green, blue }; -static float fbgamma = 1; - /* Command line options. */ int autodown; int autoup; @@ -337,24 +338,24 @@ static void shadow_draw_image(struct ida_image *img, int xoff, int yoff, unsigned int first, unsigned int last, int weight) { - unsigned int dwidth = MIN(img->i.width, fb_var.xres); - unsigned int dheight = MIN(img->i.height, fb_var.yres); + unsigned int dwidth = MIN(img->i.width, gfx->hdisplay); + unsigned int dheight = MIN(img->i.height, gfx->vdisplay); unsigned int data, offset, y, xs, ys; if (100 == weight) shadow_clear_lines(first, last); else - shadow_darkify(0, fb_var.xres-1, first, last, 100 - weight); + shadow_darkify(0, gfx->hdisplay-1, first, last, 100 - weight); /* offset for image data (image > screen, select visible area) */ offset = (yoff * img->i.width + xoff) * 3; /* offset for video memory (image < screen, center image) */ xs = 0, ys = 0; - if (img->i.width < fb_var.xres) - xs += (fb_var.xres - img->i.width) / 2; - if (img->i.height < fb_var.yres) - ys += (fb_var.yres - img->i.height) / 2; + if (img->i.width < gfx->hdisplay) + xs += (gfx->hdisplay - img->i.width) / 2; + if (img->i.height < gfx->vdisplay) + ys += (gfx->vdisplay - img->i.height) / 2; /* go ! */ for (data = 0, y = 0; @@ -377,21 +378,21 @@ shadow_draw_image(struct ida_image *img, int xoff, int yoff, static void status_prepare(void) { struct ida_image *img = flist_img_get(fcurrent); - int y1 = fb_var.yres - (face->size->metrics.height >> 6); - int y2 = fb_var.yres - 1; + int y1 = gfx->vdisplay - (face->size->metrics.height >> 6); + int y2 = gfx->vdisplay - 1; if (img) { shadow_draw_image(img, fcurrent->left, fcurrent->top, y1, y2, 100); - shadow_darkify(0, fb_var.xres-1, y1, y2, transparency); + shadow_darkify(0, gfx->hdisplay-1, y1, y2, transparency); } else { shadow_clear_lines(y1, y2); } - shadow_draw_line(0, fb_var.xres-1, y1-1, y1-1); + shadow_draw_line(0, gfx->hdisplay-1, y1-1, y1-1); } static void status_update(unsigned char *desc, char *info) { - int yt = fb_var.yres + (face->size->metrics.descender >> 6); + int yt = gfx->vdisplay + (face->size->metrics.descender >> 6); wchar_t str[128]; if (!statusline) @@ -405,14 +406,14 @@ static void status_update(unsigned char *desc, char *info) } else { swprintf(str,ARRAY_SIZE(str), L"| H - Help"); } - shadow_draw_string(face, fb_var.xres, yt, str, 1); + shadow_draw_string(face, gfx->hdisplay, yt, str, 1); - shadow_render(); + shadow_render(gfx); } static void status_error(unsigned char *msg) { - int yt = fb_var.yres + (face->size->metrics.descender >> 6); + int yt = gfx->vdisplay + (face->size->metrics.descender >> 6); wchar_t str[128]; status_prepare(); @@ -420,13 +421,13 @@ static void status_error(unsigned char *msg) swprintf(str,ARRAY_SIZE(str), L"%s", msg); shadow_draw_string(face, 0, yt, str, -1); - shadow_render(); + shadow_render(gfx); sleep(2); } static void status_edit(unsigned char *msg, int pos) { - int yt = fb_var.yres + (face->size->metrics.descender >> 6); + int yt = gfx->vdisplay + (face->size->metrics.descender >> 6); wchar_t str[128]; status_prepare(); @@ -434,7 +435,7 @@ static void status_edit(unsigned char *msg, int pos) swprintf(str,ARRAY_SIZE(str), L"%s", msg); shadow_draw_string_cursor(face, 0, yt, str, pos); - shadow_render(); + shadow_render(gfx); } static void show_exif(struct flist *f) @@ -514,7 +515,7 @@ static void show_exif(struct flist *f) } shadow_draw_text_box(face, 24, 16, transparency, linebuffer, count); - shadow_render(); + shadow_render(gfx); /* pass three -- free data */ for (tag = 0; tag < ARRAY_SIZE(tags); tag++) @@ -556,7 +557,7 @@ static void show_help(void) shadow_draw_text_box(face, 24, 16, transparency, help, ARRAY_SIZE(help)); - shadow_render(); + shadow_render(gfx); } /* ---------------------------------------------------------------------- */ @@ -615,10 +616,9 @@ console_switch(void) fb_switch_acquire(); case FB_ACTIVE: visible = 1; - ioctl(fd,FBIOPAN_DISPLAY,&fb_var); - shadow_set_palette(fd); + gfx->restore_display(); shadow_set_dirty(); - shadow_render(); + shadow_render(gfx); break; default: break; @@ -756,10 +756,10 @@ static float auto_scale(struct ida_image *img) { float xs,ys,scale; - xs = (float)fb_var.xres / img->i.width; + xs = (float)gfx->hdisplay / img->i.width; if (fitwidth) return xs; - ys = (float)fb_var.yres / img->i.height; + ys = (float)gfx->vdisplay / img->i.height; scale = (xs < ys) ? xs : ys; return scale; } @@ -790,9 +790,9 @@ static void effect_blend(struct flist *f, struct flist *t) if (weight > 100) weight = 100; shadow_draw_image(flist_img_get(f), f->left, f->top, - 0, fb_var.yres-1, 100); + 0, gfx->vdisplay-1, 100); shadow_draw_image(flist_img_get(t), t->left, t->top, - 0, fb_var.yres-1, weight); + 0, gfx->vdisplay-1, weight); if (perfmon) { pos += snprintf(linebuffer+pos, sizeof(linebuffer)-pos, @@ -801,7 +801,7 @@ static void effect_blend(struct flist *f, struct flist *t) count++; } - shadow_render(); + shadow_render(gfx); } while (weight < 100); if (perfmon) { @@ -812,7 +812,7 @@ static void effect_blend(struct flist *f, struct flist *t) " | %d/%d -> %d msec", msecs, count, msecs/count); status_update(linebuffer, NULL); - shadow_render(); + shadow_render(gfx); sleep(2); } } @@ -840,38 +840,38 @@ svga_show(struct flist *f, struct flist *prev, for (;;) { if (redraw) { redraw = 0; - if (img->i.height <= fb_var.yres) { + if (img->i.height <= gfx->vdisplay) { f->top = 0; } else { if (f->top < 0) f->top = 0; - if (f->top + fb_var.yres > img->i.height) - f->top = img->i.height - fb_var.yres; + if (f->top + gfx->vdisplay > img->i.height) + f->top = img->i.height - gfx->vdisplay; } - if (img->i.width <= fb_var.xres) { + if (img->i.width <= gfx->hdisplay) { f->left = 0; } else { if (f->left < 0) f->left = 0; - if (f->left + fb_var.xres > img->i.width) - f->left = img->i.width - fb_var.xres; + if (f->left + gfx->hdisplay > img->i.width) + f->left = img->i.width - gfx->hdisplay; } if (blend_msecs && prev && prev != f && flist_img_get(prev) && flist_img_get(f)) { effect_blend(prev, f); prev = NULL; } else { - shadow_draw_image(img, f->left, f->top, 0, fb_var.yres-1, 100); + shadow_draw_image(img, f->left, f->top, 0, gfx->vdisplay-1, 100); } status_update(desc, info); - shadow_render(); + shadow_render(gfx); if (read_ahead) { struct flist *f = flist_next(fcurrent,1,0); if (f && !f->fimg) flist_img_load(f,1); status_update(desc, info); - shadow_render(); + shadow_render(gfx); } } if (switch_last != fb_switch_state) { @@ -929,7 +929,7 @@ svga_show(struct flist *f, struct flist *prev, return KEY_Q; } else if (0 == strcmp(key, " ")) { - if (textreading && f->top < (int)(img->i.height - fb_var.yres)) { + if (textreading && f->top < (int)(img->i.height - gfx->vdisplay)) { redraw = 1; f->top += f->text_steps; } else { @@ -937,22 +937,22 @@ svga_show(struct flist *f, struct flist *prev, return KEY_SPACE; } - } else if (0 == strcmp(key, "\x1b[A") && img->i.height > fb_var.yres) { + } else if (0 == strcmp(key, "\x1b[A") && img->i.height > gfx->vdisplay) { redraw = 1; f->top -= v_steps; - } else if (0 == strcmp(key, "\x1b[B") && img->i.height > fb_var.yres) { + } else if (0 == strcmp(key, "\x1b[B") && img->i.height > gfx->vdisplay) { redraw = 1; f->top += v_steps; - } else if (0 == strcmp(key, "\x1b[1~") && img->i.height > fb_var.yres) { + } else if (0 == strcmp(key, "\x1b[1~") && img->i.height > gfx->vdisplay) { redraw = 1; f->top = 0; } else if (0 == strcmp(key, "\x1b[4~")) { redraw = 1; - f->top = img->i.height - fb_var.yres; - } else if (0 == strcmp(key, "\x1b[D") && img->i.width > fb_var.xres) { + f->top = img->i.height - gfx->vdisplay; + } else if (0 == strcmp(key, "\x1b[D") && img->i.width > gfx->hdisplay) { redraw = 1; f->left -= h_steps; - } else if (0 == strcmp(key, "\x1b[C") && img->i.width > fb_var.xres) { + } else if (0 == strcmp(key, "\x1b[C") && img->i.width > gfx->hdisplay) { redraw = 1; f->left += h_steps; @@ -972,7 +972,7 @@ svga_show(struct flist *f, struct flist *prev, 0 == strcmp(key, "J") || 0 == strcmp(key, "n") || 0 == strcmp(key, "N")) { - if (textreading && f->top < (int)(img->i.height - fb_var.yres)) { + if (textreading && f->top < (int)(img->i.height - gfx->vdisplay)) { redraw = 1; f->top += f->text_steps; } else { @@ -1065,16 +1065,16 @@ static void scale_fix_top_left(struct flist *f, float old, float new) unsigned int width, height; float cx,cy; - cx = (float)(f->left + fb_var.xres/2) / (img->i.width * old); - cy = (float)(f->top + fb_var.yres/2) / (img->i.height * old); + cx = (float)(f->left + gfx->hdisplay/2) / (img->i.width * old); + cy = (float)(f->top + gfx->vdisplay/2) / (img->i.height * old); width = img->i.width * new; height = img->i.height * new; - f->left = cx * width - fb_var.xres/2; - f->top = cy * height - fb_var.yres/2; + f->left = cx * width - gfx->hdisplay/2; + f->top = cy * height - gfx->vdisplay/2; if (textreading) { - f->text_steps = calculate_text_steps(height, fb_var.yres); + f->text_steps = calculate_text_steps(height, gfx->vdisplay); } } @@ -1380,12 +1380,12 @@ static void flist_img_load(struct flist *f, int prefetch) if (!f->seen) { struct ida_image *img = flist_img_get(f); - if (img->i.width > fb_var.xres) - f->left = (img->i.width - fb_var.xres) / 2; - if (img->i.height > fb_var.yres) { - f->top = (img->i.height - fb_var.yres) / 2; + if (img->i.width > gfx->hdisplay) + f->left = (img->i.width - gfx->hdisplay) / 2; + if (img->i.height > gfx->vdisplay) { + f->top = (img->i.height - gfx->vdisplay) / 2; if (textreading) { - f->text_steps = calculate_text_steps(img->i.height, fb_var.yres); + f->text_steps = calculate_text_steps(img->i.height, gfx->vdisplay); f->top = 0; } } @@ -1401,7 +1401,7 @@ static void flist_img_load(struct flist *f, int prefetch) static void cleanup_and_exit(int code) { shadow_fini(); - fb_clear_screen(); + fb_clear_screen(gfx); tty_restore(); fb_cleanup(); flist_print_tagged(stdout); @@ -1465,8 +1465,6 @@ main(int argc, char *argv[]) timeout = GET_TIMEOUT(); pcd_res = GET_PCD_RES(); - fbgamma = GET_GAMMA(); - fontname = cfg_get_str(O_FONT); filelist = cfg_get_str(O_FILE_LIST); @@ -1493,13 +1491,12 @@ main(int argc, char *argv[]) fprintf(stderr,"can't open font: %s\n",fontname); exit(1); } - fd = fb_init(cfg_get_str(O_DEVICE), - cfg_get_str(O_VIDEO_MODE), - GET_VT()); + gfx = fb_init(cfg_get_str(O_DEVICE), + cfg_get_str(O_VIDEO_MODE), + GET_VT()); fb_catch_exit_signals(); fb_switch_init(); - shadow_init(); - shadow_set_palette(fd); + shadow_init(gfx); signal(SIGTSTP,SIG_IGN); /* svga main loop */ @@ -1645,9 +1642,9 @@ main(int argc, char *argv[]) case KEY_VERBOSE: #if 0 /* fbdev testing/debugging hack */ { - ioctl(fd,FBIOBLANK,1); + ioctl(gfx->fb_fd,FBIOBLANK,1); sleep(1); - ioctl(fd,FBIOBLANK,0); + ioctl(gfx->fb_fd,FBIOBLANK,0); } #endif statusline = !statusline; diff --git a/fbiconfig.c b/fbiconfig.c index bfe27b8..0f1cb49 100644 --- a/fbiconfig.c +++ b/fbiconfig.c @@ -147,12 +147,6 @@ struct cfg_cmdline fbi_cfg[] = { .needsarg = 1, .desc = "pick PhotoCD resolution (1..5)", },{ - .letter = 'g', - .cmdline = "gamma", - .option = { O_GAMMA }, - .needsarg = 1, - .desc = "set display gamma (doesn't work on all hardware)", - },{ .letter = 'f', .cmdline = "font", .option = { O_FONT }, diff --git a/fbiconfig.h b/fbiconfig.h index 3abdb6d..9ed7ace 100644 --- a/fbiconfig.h +++ b/fbiconfig.h @@ -30,8 +30,6 @@ #define O_TIMEOUT O_OPTIONS, "timeout" #define O_PCD_RES O_OPTIONS, "photocd-res" -#define O_GAMMA O_OPTIONS, "gamma" - #define O_DEVICE O_OPTIONS, "device" #define O_FONT O_OPTIONS, "font" #define O_VIDEO_MODE O_OPTIONS, "video-mode" @@ -62,8 +60,6 @@ #define GET_TIMEOUT() cfg_get_int(O_TIMEOUT, 0) #define GET_PCD_RES() cfg_get_int(O_PCD_RES, 3) -#define GET_GAMMA() cfg_get_float(O_GAMMA, 1) - /* -------------------------------------------------------------------------- */ extern struct cfg_cmdline fbi_cmd[]; @@ -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(); @@ -1,18 +1,17 @@ +#include "gfx.h" + #define FB_ACTIVE 0 #define FB_REL_REQ 1 #define FB_INACTIVE 2 #define FB_ACQ_REQ 3 /* info about videomode - yes I know, quick & dirty... */ -extern struct fb_fix_screeninfo fb_fix; -extern struct fb_var_screeninfo fb_var; extern unsigned char *fb_mem; extern int fb_mem_offset; extern int fb_switch_state; /* init + cleanup */ -int fb_probe(void); -int fb_init(char *device, char *mode, int vt); +gfxstate *fb_init(char *device, char *mode, int vt); void fb_cleanup(void); void fb_catch_exit_signals(void); void fb_memset(void *addr, int c, size_t len); @@ -0,0 +1,20 @@ +#include <inttypes.h> + +typedef struct gfxstate gfxstate; + +struct gfxstate { + /* info */ + uint32_t hdisplay; + uint32_t vdisplay; + uint32_t stride; + + uint32_t bits_per_pixel; + uint32_t rlen, glen, blen, tlen; + uint32_t roff, goff, boff, toff; + + /* calls */ + void (*restore_display)(void); + + /* FIXME: legacy */ + int fb_fd; +}; |