For libpng 1.5.13 the jmpbuf pointer for the png_structp doesn't exists, we need...
[fbv.git] / fb_display.c
blobbdbc5ada6209eecdce2f000472ce4caf6a1d64fb
1 /*`
2 fbv -- simple image viewer for the linux framebuffer
3 Copyright (C) 2000 Tomasz Sterna
4 Copyright (C) 2003 Mateusz Golicz
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <asm/types.h>
30 #include <string.h>
31 #include <errno.h>
32 #include "config.h"
33 #include <linux/fb.h>
35 /* Public Use Functions:
37 * extern void fb_display(unsigned char *rgbbuff,
38 * int x_size, int y_size,
39 * int x_pan, int y_pan,
40 * int x_offs, int y_offs);
42 * extern void getCurrentRes(int *x,int *y);
46 unsigned short red[256], green[256], blue[256];
47 struct fb_cmap map332 = {0, 256, red, green, blue, NULL};
48 unsigned short red_b[256], green_b[256], blue_b[256];
49 struct fb_cmap map_back = {0, 256, red_b, green_b, blue_b, NULL};
52 int openFB(const char *name);
53 void closeFB(int fh);
54 void getVarScreenInfo(int fh, struct fb_var_screeninfo *var);
55 void setVarScreenInfo(int fh, struct fb_var_screeninfo *var);
56 void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix);
57 void set332map(int fh);
58 void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp);
59 void blit2FB(int fh, void *fbbuff, unsigned char *alpha,
60 unsigned int pic_xs, unsigned int pic_ys,
61 unsigned int scr_xs, unsigned int scr_ys,
62 unsigned int xp, unsigned int yp,
63 unsigned int xoffs, unsigned int yoffs,
64 int cpp);
66 void fb_display(unsigned char *rgbbuff, unsigned char * alpha, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs)
68 struct fb_var_screeninfo var;
69 struct fb_fix_screeninfo fix;
70 unsigned short *fbbuff = NULL;
71 int fh = -1, bp = 0;
72 unsigned long x_stride;
74 /* get the framebuffer device handle */
75 fh = openFB(NULL);
77 /* read current video mode */
78 getVarScreenInfo(fh, &var);
79 getFixScreenInfo(fh, &fix);
81 x_stride = (fix.line_length * 8) / var.bits_per_pixel;
83 /* correct panning */
84 if(x_pan > x_size - x_stride) x_pan = 0;
85 if(y_pan > y_size - var.yres) y_pan = 0;
86 /* correct offset */
87 if(x_offs + x_size > x_stride) x_offs = 0;
88 if(y_offs + y_size > var.yres) y_offs = 0;
90 /* blit buffer 2 fb */
91 fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp);
92 #if 0
93 blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres, x_pan, y_pan, x_offs, y_offs, bp);
94 #else
95 blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, bp);
96 #endif
97 free(fbbuff);
99 /* close device */
100 closeFB(fh);
103 void getCurrentRes(int *x, int *y)
105 struct fb_var_screeninfo var;
106 int fh = -1;
107 fh = openFB(NULL);
108 getVarScreenInfo(fh, &var);
109 *x = var.xres;
110 *y = var.yres;
111 closeFB(fh);
114 int openFB(const char *name)
116 int fh;
117 char *dev;
119 if(name == NULL){
120 dev = getenv("FRAMEBUFFER");
121 if(dev) name = dev;
122 else name = DEFAULT_FRAMEBUFFER;
125 if ((fh = open(name, O_RDWR)) == -1){
126 fprintf(stderr, "open %s: %s\n", name, strerror(errno));
127 exit(1);
129 return fh;
132 void closeFB(int fh)
134 close(fh);
137 void getVarScreenInfo(int fh, struct fb_var_screeninfo *var)
139 if (ioctl(fh, FBIOGET_VSCREENINFO, var)){
140 fprintf(stderr, "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno));
141 exit(1);
145 void setVarScreenInfo(int fh, struct fb_var_screeninfo *var)
147 if (ioctl(fh, FBIOPUT_VSCREENINFO, var)){
148 fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
149 exit(1);
153 void getFixScreenInfo(int fh, struct fb_fix_screeninfo *fix)
155 if (ioctl(fh, FBIOGET_FSCREENINFO, fix)){
156 fprintf(stderr, "ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno));
157 exit(1);
161 void make332map(struct fb_cmap *map)
163 int rs, gs, bs, i;
164 int r = 8, g = 8, b = 4;
166 map->red = red;
167 map->green = green;
168 map->blue = blue;
170 rs = 256 / (r - 1);
171 gs = 256 / (g - 1);
172 bs = 256 / (b - 1);
174 for (i = 0; i < 256; i++) {
175 map->red[i] = (rs * ((i / (g * b)) % r)) * 255;
176 map->green[i] = (gs * ((i / b) % g)) * 255;
177 map->blue[i] = (bs * ((i) % b)) * 255;
181 void set8map(int fh, struct fb_cmap *map)
183 if (ioctl(fh, FBIOPUTCMAP, map) < 0) {
184 fprintf(stderr, "Error putting colormap");
185 exit(1);
189 void get8map(int fh, struct fb_cmap *map)
191 if (ioctl(fh, FBIOGETCMAP, map) < 0) {
192 fprintf(stderr, "Error getting colormap");
193 exit(1);
197 void set332map(int fh)
199 make332map(&map332);
200 set8map(fh, &map332);
203 void blit2FB(int fh, void *fbbuff, unsigned char *alpha,
204 unsigned int pic_xs, unsigned int pic_ys,
205 unsigned int scr_xs, unsigned int scr_ys,
206 unsigned int xp, unsigned int yp,
207 unsigned int xoffs, unsigned int yoffs,
208 int cpp)
210 int i, xc, yc;
211 unsigned char *fb;
213 unsigned char *fbptr;
214 unsigned char *imptr;
216 xc = (pic_xs > scr_xs) ? scr_xs : pic_xs;
217 yc = (pic_ys > scr_ys) ? scr_ys : pic_ys;
219 fb = mmap(NULL, scr_xs * scr_ys * cpp, PROT_WRITE | PROT_READ, MAP_SHARED, fh, 0);
221 if(fb == MAP_FAILED)
223 perror("mmap");
224 return;
227 if(cpp == 1)
229 get8map(fh, &map_back);
230 set332map(fh);
233 fbptr = fb + (yoffs * scr_xs + xoffs) * cpp;
234 imptr = fbbuff + (yp * pic_xs + xp) * cpp;
236 if(alpha)
238 unsigned char * alphaptr;
239 int from, to, x;
241 alphaptr = alpha + (yp * pic_xs + xp);
243 for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs)
245 for(x = 0; x<xc; x++)
247 int v;
249 from = to = -1;
250 for(v = x; v<xc; v++)
252 if(from == -1)
254 if(alphaptr[v] > 0x80) from = v;
256 else
258 if(alphaptr[v] < 0x80)
260 to = v;
261 break;
265 if(from == -1)
266 break;
268 if(to == -1) to = xc;
270 memcpy(fbptr + (from * cpp), imptr + (from * cpp), (to - from - 1) * cpp);
271 x += to - from - 1;
275 else
276 for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp)
277 memcpy(fbptr, imptr, xc * cpp);
279 if(cpp == 1)
280 set8map(fh, &map_back);
282 munmap(fb, scr_xs * scr_ys * cpp);
285 inline static unsigned char make8color(unsigned char r, unsigned char g, unsigned char b)
287 return (
288 (((r >> 5) & 7) << 5) |
289 (((g >> 5) & 7) << 2) |
290 ((b >> 6) & 3) );
293 inline static unsigned short make15color(unsigned char r, unsigned char g, unsigned char b)
295 return (
296 (((r >> 3) & 31) << 10) |
297 (((g >> 3) & 31) << 5) |
298 ((b >> 3) & 31) );
301 inline static unsigned short make16color(unsigned char r, unsigned char g, unsigned char b)
303 return (
304 (((r >> 3) & 31) << 11) |
305 (((g >> 2) & 63) << 5) |
306 ((b >> 3) & 31) );
309 void* convertRGB2FB(int fh, unsigned char *rgbbuff, unsigned long count, int bpp, int *cpp)
311 unsigned long i;
312 void *fbbuff = NULL;
313 u_int8_t *c_fbbuff;
314 u_int16_t *s_fbbuff;
315 u_int32_t *i_fbbuff;
317 switch(bpp)
319 case 8:
320 *cpp = 1;
321 c_fbbuff = (unsigned char *) malloc(count * sizeof(unsigned char));
322 for(i = 0; i < count; i++)
323 c_fbbuff[i] = make8color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]);
324 fbbuff = (void *) c_fbbuff;
325 break;
326 case 15:
327 *cpp = 2;
328 s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short));
329 for(i = 0; i < count ; i++)
330 s_fbbuff[i] = make15color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]);
331 fbbuff = (void *) s_fbbuff;
332 break;
333 case 16:
334 *cpp = 2;
335 s_fbbuff = (unsigned short *) malloc(count * sizeof(unsigned short));
336 for(i = 0; i < count ; i++)
337 s_fbbuff[i] = make16color(rgbbuff[i*3], rgbbuff[i*3+1], rgbbuff[i*3+2]);
338 fbbuff = (void *) s_fbbuff;
339 break;
340 case 24:
341 case 32:
342 *cpp = 4;
343 i_fbbuff = (unsigned int *) malloc(count * sizeof(unsigned int));
344 for(i = 0; i < count ; i++)
345 i_fbbuff[i] = ((rgbbuff[i*3] << 16) & 0xFF0000) |
346 ((rgbbuff[i*3+1] << 8) & 0xFF00) |
347 (rgbbuff[i*3+2] & 0xFF);
348 fbbuff = (void *) i_fbbuff;
349 break;
350 default:
351 fprintf(stderr, "Unsupported video mode! You've got: %dbpp\n", bpp);
352 exit(1);
354 return fbbuff;