aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fb-gui.c155
-rw-r--r--fb-gui.h7
-rw-r--r--fbi.c135
-rw-r--r--fbiconfig.c6
-rw-r--r--fbiconfig.h4
-rw-r--r--fbtools.c148
-rw-r--r--fbtools.h7
-rw-r--r--gfx.h20
8 files changed, 225 insertions, 257 deletions
diff --git a/fb-gui.c b/fb-gui.c
index 3d88100..091254a 100644
--- a/fb-gui.c
+++ b/fb-gui.c
@@ -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);
}
diff --git a/fb-gui.h b/fb-gui.h
index 842a511..7b5d50e 100644
--- a/fb-gui.h
+++ b/fb-gui.h
@@ -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);
diff --git a/fbi.c b/fbi.c
index 4ccb401..ae5d7e7 100644
--- a/fbi.c
+++ b/fbi.c
@@ -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[];
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();
diff --git a/fbtools.h b/fbtools.h
index 469675c..ae53231 100644
--- a/fbtools.h
+++ b/fbtools.h
@@ -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);
diff --git a/gfx.h b/gfx.h
new file mode 100644
index 0000000..77ab172
--- /dev/null
+++ b/gfx.h
@@ -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;
+};